ECMAScript® 2024 语言规范
导言
此ecma标准定义了ECMAScript 2024语言。它是ECMAScript语言的第十五版
规范。自1997年第一版出版以来,ECMAScript已发展成为世界上
最广泛使用的通用编程语言。它最为人所知的是嵌入在网络中的语言
浏览器,但也被广泛用于服务器和嵌入式应用程序。
ECMAScript基于几种原始技术,最著名的是JavaScript(Netscape)和
JScript(微软)。该语言由Netscape的Brendan Eich发明,首次出现在该公司的
Navigator 2.0浏览器。它已出现在Netscape的所有后续浏览器和Netscape的所有浏览器中
Microsoft从Internet Explorer 3.0开始。
ECMAScript语言规范的开发始于1996年11月。这个的第一版
ECMA标准于1997年6月由ECMA大会通过。
该ECMA标准已提交给ISO/IEC JTC 1以供快速通道程序采用,并被批准为
国际标准ISO/IEC 16262,1998年4月。ECMA大会于1998年6月批准了第二个
ECMA-262版本,使其完全符合ISO/IEC 16262。第一个和第二个之间的变化
版本本质上是编辑性的。
标准第三版引入了强大的正则表达式、更好的字符串处理、新的控件
语句、try/catch异常处理、更严格的错误定义、数字输出的格式和次要
对未来语言增长的预期变化。ECMAScript标准的第三版被
1999年12月的ECMA大会,并于2002年6月作为ISO/IEC 16262:2002发布。
第三版发布后,ECMAScript与全球广泛采用
Web,它已成为基本上所有Web浏览器都支持的编程语言。重要的
开发ECMAScript第四版的工作已经完成。然而,这项工作没有完成,也没有出版
作为ECMAScript的第四版,但其中一些被纳入了第六版的开发。
ECMAScript第五版(作为ECMA-262 5th 版发布)事实上已编纂
对浏览器实现中常见的语言规范的解释并添加了
支持自第三版出版以来出现的新功能。这些功能包括
访问器
属性 ,对象的反射创建和检查,属性的程序控制
属性,额外的数组操作功能,支持JSON对象编码格式,以及严格的
提供增强错误检查和程序安全性的模式。第五版被ECMA2009年12月大会采用。
第五版提交给ISO/IEC JTC 1采用快速通道程序,并被批准为国际标准ISO/IEC 16262:2011。ECMAScript标准的5.1版包含了一些小的修正,文本与ISO/IEC
16262:2011相同。5.1版于2011年6月被Ecma大会采纳。
第六版的集中开发始于2009年,当时第五版正在准备出版。然而,在此之前,自1999年第三版发布以来,已经进行了大量的实验和语言增强设计工作。从某种意义上说,第六版的完成是十五年努力的结晶。本版的目标包括提供对大型应用程序、库创建的更好支持,并将ECMAScript用作其他语言的编译目标。其主要增强功能包括模块、类声明、词法块作用域、迭代器和生成器、用于异步编程的Promises、解构模式和正确的尾调用。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通过AsyncIterator协议和异步生成器引入了对异步迭代的支持。它还包括四个新的正则表达式特性:dotAll
标志、命名捕获组、Unicode属性转义和后行断言。最后,它还包括对象的剩余和扩展属性。
ECMAScript
2019引入了一些新的内置函数:Array.prototype
上的flat
和flatMap
用于扁平化数组,Object.fromEntries
用于直接将Object.entries
的返回值转化为新对象,以及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合并,一个值选择操作符;以及可选链,一个属性访问和函数调用操作符,当要访问/调用的值为nullish时会短路。
ECMAScript
2021,第12版,引入了字符串的replaceAll
方法;Promise.any
,一个在输入值被实现时短路的Promise组合器;AggregateError
,一种新错误类型,用于同时表示多个错误;逻辑赋值操作符(??=
、&&=
、||=
);WeakRef
,用于引用目标对象而不保留其免于垃圾回收,以及FinalizationRegistry
,用于管理在目标对象被垃圾回收时执行的清理操作的注册和取消注册;数字字面量的分隔符(1_000
);并且使Array.prototype.sort
更加精确,减少了导致实现定义 的排序顺序的不确定情况。
ECMAScript 2022,第13版,引入了顶层await
,允许在模块顶层使用关键字 ;新的类元素:公共和私有实例字段、公共和私有静态字段、私有实例方法和访问器、以及私有静态方法和访问器;类中的静态块,用于每类评估初始化;#x in obj
语法,用于测试对象上私有字段的存在;通过/d
标志的正则表达式匹配索引,提供匹配子字符串的起始和结束索引;Error
对象上的cause
属性,用于记录错误中的因果链;用于字符串、数组和类型化数组 的at
方法,允许相对索引;以及Object.hasOwn
,Object.prototype.hasOwnProperty
的便捷替代。
ECMAScript
2023,第14版,引入了Array.prototype
和TypedArray.prototype
上的toSorted
、toReversed
、with
、findLast
和findLastIndex
方法,以及Array.prototype
上的toSpliced
方法;增加了对文件开头#!
注释的支持,以更好地促进可执行ECMAScript文件;并允许在弱集合中使用大多数符号作为键。
ECMAScript
2024,第15版,增加了调整和转移ArrayBuffers和SharedArrayBuffers大小的功能;添加了用于创建具有更高级功能的字符串集的RegExp/v
标志;引入了用于构建Promise的便捷方法Promise.withResolvers
、用于数据聚合的Object.groupBy
和Map.groupBy
方法、用于异步等待共享内存更改的Atomics.waitAsync
方法,以及用于检查和确保字符串仅包含格式良好的Unicode的String.prototype.isWellFormed
和String.prototype.toWellFormed
方法。
代表许多组织的数十个人在Ecma
TC39中对这一版本的开发以及之前的版本做出了非常重要的贡献。此外,还出现了一个支持TC39的ECMAScript工作的活跃社区。这个社区审查了无数草案,提交了数千个错误报告,进行了实现实验,贡献了测试套件,并向全球开发者社区介绍了ECMAScript。不幸的是,不可能识别和感谢每一个为这项工作做出贡献的人和组织。
Allen Wirfs-Brock
ECMA-262,第六版项目编辑
Brian Terlson
ECMA-262,第七版至第十版项目编辑
Jordan Harband
ECMA-262,第十版至第十二版项目编辑
Shu-yu Guo
ECMA-262,第十二版至第十五版项目编辑
Michael Ficarra
ECMA-262,第十二版至第十五版项目编辑
Kevin Gibbons
ECMA-262,第十二版至第十五版项目编辑
1 范围
本标准定义了ECMAScript 2024通用编程语言。
2 一致性
符合ECMAScript规范的实现必须提供并支持本规范中描述的所有类型、值、对象、属性、函数和程序语法及语义。
符合ECMAScript规范的实现必须按照最新版本的Unicode标准和ISO/IEC 10646解释源文本输入。
提供支持不同语言和国家的语言和文化习俗的应用编程接口(API)的符合ECMAScript规范的实现必须实现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 宿主环境 ,包括表示窗口、菜单、弹出窗口、对话框、文本区域、锚点、框架、历史记录、Cookies以及输入/输出的对象。此外,宿主环境 还提供了一种将脚本代码附加到事件(如焦点更改、页面和图像加载、卸载、错误和中止、选择、表单提交和鼠标操作)的方法。脚本代码出现在HTML中,显示的页面是用户界面元素和固定和计算文本及图像的组合。脚本代码对用户交互有反应,因此不需要主程序。
Web服务器为服务器端计算提供了不同的宿主环境 ,包括表示请求、客户端和文件的对象;以及锁定和共享数据的机制。通过结合使用浏览器端和服务器端脚本,可以在客户端和服务器之间分配计算,同时为基于Web的应用程序提供定制的用户界面。
每个支持ECMAScript的Web浏览器和服务器都提供自己的宿主环境 ,从而完成ECMAScript的执行环境。
4.2 宿主和实现
为了帮助将ECMAScript集成到宿主环境 中,本规范将某些功能的定义(例如,抽象操作 )全部或部分地推迟到本规范之外的来源。在编辑上,本规范区分了以下几种推迟定义的方式。
实现 是进一步定义附录D 中列出的功能或那些标记为实现定义 或实现近似 的功能的外部来源。在非正式使用中,实现是指具体的人工制品,例如特定的网络浏览器。
实现定义 的功能是指将其定义推迟到外部来源而没有进一步的限定。本规范对特定行为没有做出任何建议,符合规范的实现可以在本规范提出的约束范围内选择任何行为。
实现近似 的功能是指将其定义推迟到外部来源,同时建议一种理想行为。虽然符合规范的实现可以在本规范提出的约束范围内选择任何行为,但鼓励它们尽量接近理想。一些数学操作,例如Math.exp
,属于实现近似 。
宿主 是进一步定义附录D 中列出的功能,但不进一步定义其他实现定义 或实现近似 功能的外部来源。在非正式使用中,宿主 是指以相同方式通过附录D 与本规范接口的所有实现集,例如所有网络浏览器的集合。宿主 通常是一个外部规范,例如WHATWG HTML (https://html.spec.whatwg.org/ )。换句话说,宿主定义 的功能通常在外部规范中进一步定义。
宿主挂钩 是一个由外部来源全部或部分定义的抽象操作。所有 宿主挂钩 必须列在附录 D 中。宿主挂钩 必须至少符合以下要求:
宿主定义 的功能是将其定义推迟到外部来源而没有进一步的限定,并列在附录 D 中。不是 宿主 的实现也可以提供 宿主定义 的功能定义。
宿主环境 是所有 宿主定义 功能的特定定义选择。宿主环境 通常包括允许获取输入和提供输出的对象或函数,作为 宿主定义 属性的一部分的 全局对象 。
本规范遵循始终使用最具体术语的编辑约定。例如,如果一个功能是 宿主定义
的,则不应称其为 实现定义 。
宿主和实现可以通过本规范中定义的语言类型、规范类型、抽象操作 、语法生成、内在对象和内在符号与本规范接口。
4.3 ECMAScript 概述
以下是 ECMAScript 的非规范性概述,并未描述该语言的所有部分。该概述不属于标准的正式部分。
ECMAScript 是基于对象的:基本语言和宿主 功能由对象提供,ECMAScript
程序是一个相互通信的对象集合。在 ECMAScript 中,对象 是具有零个或多个 属性 的集合,每个属性都有确定如何使用该属性的 特性 ——
例如,当属性的可写特性(Writable attribute)设置为 false 时,任何试图通过执行的 ECMAScript
代码分配不同值给该属性的操作都会失败。属性是包含其他对象、原始值 或 函数
的容器。原始值是以下内置类型之一的成员:Undefined 、Null 、Boolean 、Number 、BigInt 、String 和
Symbol ;对象是内置类型 Object 的成员;函数是可调用对象。通过属性与对象关联的函数称为 方法 。
ECMAScript 定义了一组 内置对象 ,完善了 ECMAScript 实体的定义。这些内置对象包括 全局对象 ;对语言的 运行时语义 基本的对象,包括
Object
、Function
、Boolean
、Symbol
及各种 Error
对象;表示和操作数值的对象,包括 Math
、Number
和 Date
;处理文本的对象 String
和
RegExp
;值的索引集合的对象,包括 Array
和九种不同类型的元素具有特定数值表示的 Typed Arrays;键控集合,包括 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 实现近似 (implementation-approximated)
一个 实现近似
设施是由外部来源全部或部分定义的,但在本规范中有推荐的理想行为。
4.4.2 实现定义 (implementation-defined)
一个 实现定义 设施是由外部来源全部或部分定义的。
4.4.3 宿主定义 (host-defined)
与 实现定义 相同。
注
4.4.4 类型 (type)
数据值集合,定义见 第 6 章 。
4.4.5 原始值 (primitive value)
是 Undefined、Null、Boolean、Number、BigInt、Symbol 或 String 类型中的一个成员,定义见 第 6 章 。
注
4.4.6 对象 (object)
Object 类型的成员。
注
对象是属性的集合,并且有一个单一的原型对象。原型可以是 null 。
4.4.7 构造函数 (constructor)
函数对象 ,用于创建和初始化对象。
注
构造函数的 prototype 属性的值是一个原型对象,用于实现继承和共享属性。
4.4.8 原型 (prototype)
为其他对象提供共享属性的对象。
注
当一个 构造函数 创建一个对象时,该对象隐式地引用了该构造函数的 prototype 属性,用于解析属性引用。构造函数的 prototype 属性可以通过程序表达式
constructor .prototype
引用,并且添加到对象原型中的属性通过继承在所有共享该原型的对象中共享。或者,可以使用
Object.create
内置函数创建具有显式指定原型的新对象。
4.4.9 普通对象 (ordinary object)
具有所有对象必须支持的基本内部方法默认行为的对象
4.4.10 特殊对象 (exotic object)
在一个或多个基本内部方法上不具有默认行为的对象
注
4.4.11 标准对象 (standard object)
其语义由本规范定义的对象
4.4.12 内置对象 (built-in object)
由 ECMAScript 实现指定和提供的对象
注
标准内置对象在本规范中定义。ECMAScript 实现可以指定和提供其他种类的内置对象。
4.4.13 未定义值 (undefined value)
当变量未被赋值时使用的原始值
4.4.14 Undefined 类型 (Undefined type)
唯一值为 undefined 的类型
4.4.15 空值 (null value)
表示故意缺少任何对象值的原始值
4.4.16 Null 类型 (Null type)
唯一值为 null 的类型
4.4.17 布尔值 (Boolean value)
属于 Boolean 类型
的成员
注
4.4.18 Boolean 类型 (Boolean type)
由原始值 true 和 false 组成的类型
4.4.19 Boolean 对象 (Boolean object)
属于 对象类型 的成员,是标准内置 Boolean 构造函数 的实例
注
Boolean 对象是通过在 new
表达式中使用 Boolean 构造函数
并提供一个布尔值作为参数来创建的。生成的对象具有一个内部插槽,其值为布尔值。可以将 Boolean 对象强制转换为布尔值。
4.4.20 字符串值 (String value)
原始值,是一个 有限 的有序序列,包含零个或多个 16 位无符号 整数
注
字符串值是 字符串类型
的成员。序列中的每个 整数 值通常代表 UTF-16 文本的单个 16 位单元。然而,ECMAScript
对这些值没有任何限制或要求,除了它们必须是 16 位无符号 整数 。
4.4.21 字符串类型 (String type)
所有可能的字符串值的集合
4.4.22 字符串对象 (String object)
属于 对象类型 的成员,是标准内置字符串 构造函数 的实例
注
字符串对象是通过在 new
表达式中使用字符串 构造函数
并提供一个字符串值作为参数来创建的。生成的对象具有一个内部插槽,其值为字符串值。可以通过将字符串 构造函数 作为函数调用来将字符串对象强制转换为字符串值 (22.1.1.1 )。
4.4.23 Number 值 (Number value)
对应双精度 64 位二进制格式 IEEE 754-2019 值的原始值
注
Number 值是 Number 类型
的成员,是数字的直接表示。
4.4.24 Number 类型 (Number type)
所有可能的 Number 值的集合,包括特殊的“非数值” (NaN) 值、正无穷大和负无穷大
4.4.25 Number 对象 (Number object)
属于 对象类型 的成员,是标准内置 Number 构造函数 的实例
注
Number 对象是通过在 new
表达式中使用 Number 构造函数 并提供一个 Number
值作为参数来创建的。生成的对象具有一个内部插槽,其值为 Number 值。可以通过将 Number 构造函数 作为函数调用来将 Number 对象强制转换为 Number 值
(21.1.1.1 )。
4.4.26 无穷大 (Infinity)
表示正无穷大的 Number 值
4.4.27 NaN
表示 IEEE 754-2019 “非数值” 的 Number 值
4.4.28 BigInt 值 (BigInt value)
对应任意精度 整数 值的原始值
4.4.29 BigInt 类型 (BigInt type)
所有可能的 BigInt 值的集合
4.4.30 BigInt 对象 (BigInt object)
属于 对象类型 的成员,是标准内置 BigInt 构造函数 的实例
4.4.31 Symbol 值 (Symbol value)
表示唯一的、非字符串对象 属性键 的原始值
4.4.32 Symbol 类型 (Symbol type)
所有可能的 Symbol 值的集合
4.4.33 Symbol 对象 (Symbol object)
属于 对象类型 的成员,是标准内置 Symbol 构造函数 的实例
4.4.34 函数 (function)
属于 对象类型 的成员,可以作为子例程调用
注
除了它的属性之外,函数还包含可执行代码和状态,这些代码和状态决定了它在调用时的行为。函数的代码可以是 ECMAScript 编写的,也可以不是。
4.4.35 内置函数 (built-in function)
内置对象,是一个函数
注
内置函数的例子包括 parseInt
和 Math.exp
。宿主 或实现可能提供本规范中未描述的其他内置函数。
4.4.36 内置构造函数 (built-in constructor)
内置函数,是一个 构造函数
注
内置 构造函数 的例子包括 Object
和
Function
。宿主 或实现可能提供本规范中未描述的其他内置 构造函数 。
4.4.37 属性 (property)
对象的一部分,关联一个键(字符串值或 Symbol 值)和一个值
注
根据属性的形式,值可以直接表示为数据值(原始值、对象或 函数对象 )或通过一对访问器函数间接表示。
4.4.38 方法 (method)
作为属性值的函数
注
当函数作为对象的方法调用时,对象会作为其 this 值传递给函数。
4.4.39 内置方法 (built-in method)
作为内置函数的方法
注
标准内置方法在本规范中定义。宿主 或实现可能提供本规范中未描述的其他内置方法。
4.4.40 属性 (attribute)
定义属性某些特性的内部值
4.4.41 自有属性 (own property)
直接包含在对象中的属性
4.4.42 继承属性 (inherited property)
对象的属性,不是自有属性,但它是对象原型的属性(自有属性或继承属性)
4.5 本规范的组织结构 (Organization of This Specification)
本规范的其余部分组织如下:
第 5 节定义了整个规范中使用的符号约定。
第 6 节到第 10 节定义了
ECMAScript 程序运行的执行环境。
第 11 节到第 17 节定义了实际的
ECMAScript 编程语言,包括其语法编码和所有语言特性的执行语义。
第 18 节到第 28
节定义了 ECMAScript 标准库。它们包括所有可供 ECMAScript 程序在执行时使用的标准对象的定义。
第 29 节描述了对 SharedArrayBuffer 支持的内存的访问和
Atomics 对象的方法的内存一致性模型。
5 符号约定
5.1 句法和词法语法
5.1.1 上下文无关文法
一个上下文无关文法 由若干生成式 组成。每个生成式的左侧 都有一个抽象符号,称为非终结符 ,右侧则是一系列零个或多个非终结符和终结符 符号。对于每个文法,终结符号来自指定的字母表。
链生成式 是右侧有且只有一个非终结符号以及零个或多个终结符号的生成式。
从一个由单个特殊非终结符组成的句子开始,称为目标符号 ,给定的上下文无关文法指定了一种语言 ,即通过不断将序列中的任何非终结符替换为其左侧为该非终结符的生成式的右侧所能产生的终结符号的(可能是无限的)集合。
5.1.2 词法和正则表达式文法
ECMAScript 的词法文法 在 12
章中给出。该文法的终结符是符合 SourceCharacter 规则的 Unicode
代码点,这些规则定义在 11.1 章中。它定义了一组生成式,从 目标符号 InputElementDiv 、InputElementTemplateTail 、InputElementRegExp 、InputElementRegExpOrTemplateTail
或 InputElementHashbangOrRegExp
开始,描述了如何将这些代码点的序列转换为输入元素的序列。
除空白和注释外的输入元素构成 ECMAScript 语法文法的终结符,称为 ECMAScript 标记 。这些标记是 ECMAScript 语言的 保留字 、标识符、字面量和标点符号。此外,行终止符虽然不被视为标记,但也成为输入元素流的一部分,并指导自动分号插入过程(12.10 )。简单的空白和单行注释被丢弃,不会出现在语法文法的输入元素流中。如果一个
MultiLineComment (即形式为
/*
…*/
的注释,不论是否跨越多行)不包含行终止符,则它同样会被丢弃;但如果 MultiLineComment
包含一个或多个行终止符,则它将被一个单一的行终止符替代,成为语法文法输入元素流的一部分。
ECMAScript 的正则表达式文法 在 22.2.1 章中给出。该文法的终结符也是由 SourceCharacter
定义的代码点。它定义了一组生成式,从 目标符号 Pattern
开始,描述了如何将代码点的序列转换为正则表达式模式。
词法和正则表达式文法的生成式通过两个冒号 “:: ” 作为分隔标点来区分。这两种文法共享一些生成式。
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 是补充文法中的非终结符。这意味着:
使用 N 作为目标符号 重新解析最初由 P
匹配的标记序列。如果 N 采用文法参数,则它们设置为与最初解析 P 时相同的值。
如果标记序列可以解析为 N 的单个实例,并且没有剩余标记,则:
我们将该 N 的实例(解析节点,在给定 P 的情况下是唯一的)称为“由 P 覆盖的 N ”。
N 及其派生生成式的所有早期错误规则也适用于由 P 覆盖的 N 。
否则(如果解析失败),则为早期语法错误。
5.1.5 语法标记
5.1.5.1 终结符号
在ECMAScript语法中,一些终结符号显示为固定宽度
字体。这些符号应当按照书写的样子准确出现在源文本中。以这种方式指定的所有终结符号码点都应被理解为来自基本拉丁块的适当Unicode码点,而不是来自其他Unicode范围的类似看起来的码点。终结符号中的一个码点不能通过\
UnicodeEscapeSequence 来表达。
在其终结符号是单个Unicode码点的语法中(即,词汇、RegExp和数值字符串语法),连续的多个固定宽度码点出现在一个生产中,是一种简单的速记,用于表示相同的码点序列,写作独立的终结符号。
例如,产生式:
HexIntegerLiteral
::
0x
HexDigits
是以下的简写形式:
HexIntegerLiteral
::
0
x
HexDigits
相比之下,在句法语法中,连续的固定宽度码点构成一个单独的终结符号。
终结符号还有其他两种形式:
5.1.5.2 非终结符号与生产规则
非终结符号显示为斜体 类型。非终结(也称为“产生式”)的定义是由被定义的非终结名称开始,后面跟着一个或多个冒号(冒号的数量表示生产所属的语法)。然后,非终结的一个或多个备选右侧在后续行中跟随。例如,句法定义:
WhileStatement
:
while
(
Expression
)
Statement
说明非终结WhileStatement
表示关键字while
,后跟一个左括号,然后是一个Expression ,
后跟一个右括号,然后是一个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
::
任意 Unicode 代码点
<5.2 算法约定
该规范经常使用编号列表来指定算法中的步骤。这些算法用于精确指定 ECMAScript 语言结构的所需语义。这些算法并不意味着必须使用任何特定的实现技术。实际上,可能有更有效的算法可用于实现给定的功能。
算法可以明确地用一个有序的、逗号分隔的别名序列参数化,这些别名在算法步骤中可用于引用在该位置传入的参数。可选参数用方括号([ , name
])表示,与算法步骤中的必需参数没有区别。参数列表的末尾可以出现一个剩余参数,以省略号(, ...name )表示。剩余参数捕获所有在必需参数和可选参数之后提供的参数,这些参数被编入一个
列表 。如果没有这样的额外参数,那么这个
列表 将为空。
算法步骤可以细分为顺序子步骤。子步骤是缩进的,并且本身可以进一步分为缩进的子步骤。用大纲编号约定来标识子步骤,第一层子步骤用小写字母标记,第二层子步骤用小写罗马数字标记。如果需要超过三个层级,这些规则将重复,第四层使用数字标签。例如:
1. 顶层步骤
a. 子步骤。
b. 子步骤。
i. 子子步骤。
1. 子子子步骤
a. 子子子子步骤
i. 子子子子子步骤
步骤或子步骤可以作为一个“if”谓词编写,条件化其子步骤。在这种情况下,只有当谓词为真时,子步骤才会被应用。如果步骤或子步骤以“else”一词开头,它是一个谓词,是与同一层级前一个“if”谓词步骤的否定。
步骤可以指定其子步骤的迭代应用。
以“Assert (断言):”开头的步骤断言其算法的不变条件。这种断言用来明确那些否则会是隐含的算法不变性。这样的断言不增加额外的语义要求,因此实现无需检查。它们仅用于澄清算法。
算法步骤可以使用“Let x be
someValue ”的形式声明任何值的命名别名。这些别名类似于引用,x 和someValue 都指向相同的底层数据,对任何一个的修改都对双方可见。如果算法步骤想要避免这种类似引用的行为,应该明确地复制右侧值:“Let
x be a copy of someValue ”创建了someValue 的一个浅拷贝。
一旦声明,别名可以在任何后续步骤中被引用,并且不能从别名声明之前的步骤中被引用。别名可以使用“Set x to someOtherValue ”的形式进行修改。
5.2.1 抽象操作
为了便于在本规范的多个部分中使用,一些算法被称为抽象操作 ,它们被命名并以参数化的函数形式编写,以便可以从其他算法中通过名称引用它们。抽象操作通常使用函数应用风格引用,如
OperationName(arg1 , arg2 )。一些抽象操作被视为类似类的规范抽象中多态分派的方法。这种类似方法的抽象操作通常使用方法应用风格引用,例如
someValue .OperationName(arg1 , arg2 )。
5.2.2 语法导向操作
一个语法导向操作 是一个命名操作,其定义包括多个算法,每个算法都与ECMAScript语法之一的一个或多个产生式相关联。具有多个替代定义的产生式通常会为每个替代定义有一个独特的算法。当一个算法与一个语法产生式相关联时,它可以引用产生式替代的终结符和非终结符,就好像它们是算法的参数一样。在这种方式下使用时,非终结符引用在解析源文本时匹配的实际替代定义。由语法产生式匹配的 源文本 或由其衍生的解析节点 是从参与匹配的第一个终结符开始到参与匹配的最后一个终结符结束的源文本部分。
当一个算法与一个产生式替代相关联时,该替代通常显示时不包括任何“[ ]”语法注释。这样的注释只应影响替代的语法识别,对替代的相关语义没有影响。
语法导向操作通过使用下列算法中的步骤1 、3 和4 的约定,通过解析节点和可选的其他参数调用。
1.
让status 为SyntaxDirectedOperation of SomeNonTerminal 。
2. 让someParseNode 为一些源文本的解析。
3.
执行someParseNode 的SyntaxDirectedOperation。
4.
带参数"value" 执行someParseNode 的SyntaxDirectedOperation。
除非另有明确规定,所有链产生式 都隐含为其左侧非终结符的每个操作提供定义。隐含的定义简单地重新应用同一个操作和相同的参数(如果有的话)到链产生式 的唯一右侧非终结符,然后返回结果。例如,假设某个算法有一个步骤形式:“返回评估 of
块 ”,并且存在一个产生式:
块 :
{
语句列表
}
但是评估 操作并未将算法与该产生式关联。在这种情况下,评估 操作隐含地包括如下形式的关联:
运行时语义:评估
块 :
{
语句列表
}
1. 返回评估 of 语句列表 。
5.2.3 运行时语义
需要在运行时调用以指定语义的算法称为运行时语义 。运行时语义由抽象操作 或语法导向操作 定义。
5.2.3.1 完成(completionRecord )
抽象操作完成接受参数completionRecord (一个完成记录 ),并返回一个完成记录 。此操作用于强调正在返回一个完成记录 。在被调用时,它执行以下步骤:
1. 断言 :completionRecord
是一个完成记录 。
2. 返回completionRecord 。
5.2.3.2 抛出异常
算法步骤中提到抛出异常的,如:
1. 抛出一个TypeError 异常。
意味着与以下内容相同:
1. 返回ThrowCompletion (新创建的TypeError 对象)。
5.2.3.3 ReturnIfAbrupt
算法步骤中提到或等同于以下内容:
1. ReturnIfAbrupt (argument )。
意味着:
1. Assert :argument 是一个Completion
Record 。
2. 如果 argument 是一个abrupt
completion ,返回Completion (argument )。
3. 否则,将 argument 设置为 argument .[[Value]] 。
算法步骤中提到或等同于:
1. ReturnIfAbrupt (AbstractOperation())。
意味着:
1. 让 hygienicTemp 是 AbstractOperation()。
2. Assert :hygienicTemp
是一个Completion
Record 。
3. 如果 hygienicTemp 是一个abrupt
completion ,返回Completion (hygienicTemp )。
4. 否则,将 hygienicTemp 设置为 hygienicTemp .[[Value]] 。
hygienicTemp 是短暂的,仅在涉及 ReturnIfAbrupt 的步骤中可见。
算法步骤中提到或等同于:
1. 让 result 是 AbstractOperation(ReturnIfAbrupt (argument ))。
意味着:
1. Assert :argument 是一个Completion
Record 。
2. 如果 argument 是一个abrupt
completion ,返回Completion (argument )。
3. 否则,将 argument 设置为 argument .[[Value]] 。
4. 让 result 是 AbstractOperation(argument )。
5.2.3.4 ReturnIfAbrupt 简写
在抽象操作 和语法导向操作 调用时,前缀为?
表示应当应用ReturnIfAbrupt 到产生的完成记录 。例如,步骤:
1. ? OperationName().
等同于以下步骤:
1. ReturnIfAbrupt (OperationName())。
同样,对于方法应用风格,步骤:
1. ? someValue .OperationName().
等同于:
1. ReturnIfAbrupt (someValue .OperationName())。
同样地,前缀!
用来表示以下对抽象或语法导向操作 的调用绝不会返回一个突然完成 ,并且结果中的完成记录 的[[Value]] 字段应当代替操作的返回值使用。例如,步骤:
1. 让 val 是 ! OperationName().
等同于以下步骤:
1. 让 val 是 OperationName()。
2. Assert :val 是一个正常完成 。
3. 将 val 设置为 val .[[Value]] 。
语法导向操作 在运行时语义 中使用这种简写,通过在操作调用前放置!
或?
:
1. 执行 ! SyntaxDirectedOperation of
NonTerminal 。
5.2.3.5 隐式正常完成
在声明返回完成记录 的抽象操作 和所有内置函数中,返回的值首先传递给NormalCompletion ,并使用其结果。此规则不适用于Completion 算法内部,或当返回的值在该步骤中明确标记为完成记录 的情况;这些情况包括:
如果通过任何其他方式从这样的抽象操作中返回完成记录 ,将是一个编辑错误。例如,在这些抽象操作 中,
1. 返回true 。
意味着与任何一种
1. 返回NormalCompletion (true )。
或
1. 让completion 是NormalCompletion (true )。
2. 返回Completion (completion )。
或
1. 返回完成记录 {
[[Type]] : normal , [[Value]] : true , [[Target]] :
empty }。
注意,通过ReturnIfAbrupt 扩展,允许以下示例,因为在扩展的步骤中,应用Completion 的结果在突然情况下直接返回,并且在正常情况下解包后隐式应用NormalCompletion 。
1. 返回 ? completion 。
以下示例将是一个编辑错误,因为在该步骤中没有注明正在返回完成记录 。
1. 让completion 是NormalCompletion (true )。
2. 返回completion 。
5.2.4 静态语义
无上下文语法并不足以表达所有定义流式输入元素是否形成可评估的 ECMAScript Script 或 Module 的规则。在某些情况下,需要使用 ECMAScript
算法约定或描述性要求来表达额外的规则。这些规则始终与语法的产生式相关联,并称为产生式的静态语义 。
静态语义规则具有名称,并通常使用算法定义。命名的静态语义规则与语法产生式相关联,具有多个备选定义的产生式通常对每个适用的命名静态语义规则有一个单独的算法。
静态语义规则的一种特殊类型是早期错误规则 。早期错误 规则定义了特定语法产生式相关的早期错误 条件(参见章节17 )。大多数早期错误 规则的评估在本规范的算法中未显式调用。符合要求的实现必须在首次评估Script 或Module 之前,验证用于解析该Script 或Module 的所有早期错误 规则。如果违反了任何早期错误 规则,则Script 或Module 无效,无法评估。
5.2.5 数学运算
本规范参考以下数值类型:
在本规范的术语中,数值使用下标后缀来区分不同的数值类型。下标 𝔽 表示数字(Numbers),下标 ℤ 表示大整数(BigInts)。没有下标后缀的数值指代
数学值 。
数值运算符(如 +、×、= 和 ≥)根据操作数的类型确定其操作。当应用于 数学值 时,这些运算符指代通常的数学运算。当应用于 扩展数学值
时,这些运算符指代扩展实数上的通常数学运算;未定义的不定形式在本规范中不予定义,其使用应视为编辑错误。当应用于数字(Numbers)时,这些运算符指代 IEEE
754-2019 中的相关运算。当应用于大整数(BigInts)时,这些运算符指代大整数的 数学值 。
一般来说,当本规范提到数值时,例如“y 的长度”或“由四位十六进制数字表示的 整数 ”,未明确指定数值类型时,默认指代 数学值 。明确指代数字(Number)或大整数(BigInt)数值的短语将以明确标注方式出现;例如,“数字的数值 ,用于代码点数量…”或“大整数的数值 …。”
不定义混合类型操作数(例如数字和 数学值 )的数值运算符,其应视为本规范中的编辑错误。
本规范中大多数数值以十进制表示;同时也使用形如 0x 后跟数字 0-9 或 A-F 的十六进制值。
当本规范中使用术语 整数 时,指的是在 数学值 集合中的 整数 ,除非另有说明。当本规范中使用术语 整数数字 时,指的是数值其 数学值 在 整数 集合中。
本文档中对 数学值 、数字或大整数之间的转换总是明确的。从 数学值 或 扩展数学值 x
到数字的转换表示为“数字的数值 x ”或 𝔽(x ) ,并在 6.1.6.1
中定义。从整数或大整数 x 到大整数的转换表示为“大整数的数值 x ”或
ℤ(x ) 。从数字或大整数 x 到 数学值 的转换表示为“数学值的数值 x ”,或 ℝ(x ) 。对于 数学值的数值
+0 𝔽 和 -0 𝔽 ,其为 数学值 0。对于非 有限
值,其 数学值的数值 未定义。对于 x 的
扩展数学值的数值 ,其为 数学值的数值 ,对于
有限 值为 +∞
和 -∞,对于 +∞ 𝔽 和 -∞ 𝔽 分别为 +∞ 和 -∞,对于
NaN 未定义。
数学函数 abs(x ) 计算 x 的绝对值,如果
x < 0,则结果为 -x ,否则结果为 x 本身。
数学函数 min(x1 , x2 , ...,
xN ) 计算 x1 到 xN 中的最小值。数学函数 max(x1 , x2 , ..., xN ) 计算 x1 到 xN
中的最大值。这些数学函数的定义域和值域为 扩展数学值 。
记法 “x modulo
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
的最大 整数 (接近 +∞)。
注
floor (x ) = x -
(x modulo 1) .
数学函数 truncate(x )
通过朝零方向舍入移除 x 的小数部分,如果 x < 0,则产生 -floor (-x ) ,否则产生
floor (x ) 。
数学函数 min ,
max ,
abs ,
floor ,
和 truncate 对于 Numbers 和 BigInts
都没有定义,任何使用具有非 数学值 参数的方法在本规范中应视为编辑错误。
从下界 a 到上界 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 语言值
都被比较是否相等。在比较相等性时,值可以分为两类。如果所有的固有特性(如 整数 的大小或序列的长度)都相同,则没有身份标识的值 与其他没有身份标识的值相等。没有身份标识的值可以在未先前引用的情况下通过完全描述其特性来显示。相反,每个带有身份标识的值 都是唯一的,因此只与自身相等。带有身份标识的值类似于没有身份标识的值,但具有一个额外的不可预测、不可更改、全局唯一的特征,称为身份 。对现有带有身份标识的值的引用不能仅通过描述来显示,因为身份本身是无法描述的;相反,必须明确地将对这些值的引用从一个地方传递到另一个地方。一些带有身份标识的值是可变的,因此可以在原地更改其特性(除了其身份),从而使所有持有该值的人都能观察到新的特性。没有身份标识的值永远不等于带有身份标识的值。
从本规范的角度来看,“is”一词用于比较两个值是否相等,例如“如果bool 为true ,则...”,而“contains”一词用于使用相等性比较在列表中搜索值,例如“如果list 包含一个Record r ,使得r .[[Foo]] 为true ,则...”。值的规范身份 决定了这些比较的结果,并在本规范中是公理性的。
从 ECMAScript 语言的角度来看,语言值使用SameValue 抽象操作及其传递调用的抽象操作 进行相等性比较。这些比较的算法操作决定了ECMAScript
语言值 的语言身份 。
对于规范值,没有规范身份的值包括但不限于:数学值 和扩展数学值 ;ECMAScript
源文本 ,代理对 ,指令前言 等;UTF-16
代码单元;Unicode 代码点;枚举 ;抽象操作 ,包括语法导向操作 ,宿主钩子 等;有序对。
具有规范身份的规范值包括但不限于:记录 的任何种类,包括属性描述符 ,私有元素 等;解析节点 ;列表 ;集合 和关系 ;抽象闭包 ;数据块 ;私有名称 ;执行上下文 和执行上下文堆栈 ;代理标识符 ;以及等待列表记录 。
规范身份对于所有ECMAScript
语言值 都与语言身份一致,除了由Symbol.for 生成的Symbol值。没有规范身份和语言身份的ECMAScript语言值包括:undefined ,null ,布尔值 ,字符串 ,数字 ,和大整数 。具有规范身份和语言身份的ECMAScript语言值包括:Symbol ,但不包括由Symbol.for 生成的Symbol值,以及对象 。
6 ECMAScript 数据类型和值
本规范中的算法操作值,每个值都有一个关联的类型。可能的值类型正是本条款中定义的那些类型。类型进一步分为ECMAScript
语言类型 和规范类型。
在本规范中,“Type(x )”表示“x 的类型 ”,其中“类型”指的是本条款中定义的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 String 类型
String 类型 是所有有序序列的集合,这些序列由零个或多个 16
位无符号整数 值(“元素”)组成,最多可以有 2** 53 - 1 个元素。String 类型通常用于表示运行中的 ECMAScript 程序中的文本数据,其中 String
中的每个元素都被视为一个 UTF-16 代码单元值。每个元素被视为占据序列中的一个位置。这些位置使用非负整数 进行索引。第一个元素(如果有)位于索引 0,下一个元素(如果有)位于索引
1,依此类推。String 的长度是其中的元素数(即 16 位值)。空字符串的长度为零,因此不包含任何元素。
不解释 String 内容的 ECMAScript 操作不应用进一步的语义。对解释 String 值的操作将每个元素视为单个 UTF-16 代码单元。然而,ECMAScript
不限制这些代码单元的值或关系,因此进一步解释 String 内容为 UTF-16 编码的 Unicode 代码点序列的操作必须考虑到格式不正确的子序列。这些操作对于每个数值位于从 0xD800 到
0xDBFF(由 Unicode 标准定义为leading
surrogate ,或更正式地称为high-surrogate code unit )的代码单元,以及每个数值位于从 0xDC00 到
0xDFFF(定义为trailing
surrogate ,或更正式地称为low-surrogate code unit )的代码单元使用以下规则:
一个既不是前导代理对 也不是后继代理对 的代码单元,将被解释为具有相同值的代码点。
两个代码单元的序列,其中第一个代码单元 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
等...”(每个参数是一个字符串值、代码单元或代码单元的序列)表示的是一个字符串值,其代码单元的序列是每个参数(按顺序)的代码单元的连接(按顺序)。
短语“从 inclusiveStart 到 exclusiveEnd 的 子字符串 ”(其中
S 是一个字符串值或代码单元序列,而 inclusiveStart 和 exclusiveEnd 是整数 )表示由 S 的连续代码单元组成的字符串值,开始于索引
inclusiveStart 并在索引 exclusiveEnd 之前立即结束(当 inclusiveStart =
exclusiveEnd 时为空字符串)。如果省略了“to”后缀,则使用 S 的长度作为 exclusiveEnd 的值。
短语“ASCII 单词字符 ”表示以下字符串值,它仅由 Unicode 基本拉丁语块中的每个字母和数字以及
U+005F(下划线)组成:
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_" .
出于历史原因,它对各种算法具有重要意义。
6.1.4.1 StringIndexOf ( string , searchValue ,
fromIndex )
抽象操作 StringIndexOf 接受参数 string (一个字符串)、searchValue (一个字符串)和 fromIndex
(一个非负 整数 )并返回一个
整数 。它在被调用时执行以下步骤:
1. 让 len 为 string 的长度。
2. 如果 searchValue 是空字符串且 fromIndex ≤
len ,返回 fromIndex 。
3. 让 searchLen 为 searchValue 的长度。
4. 对于每个 整数
i 使得 fromIndex ≤ i ≤ len - searchLen ,按升序执行:
a. 让 candidate 为 string 从 i 到
i + searchLen 的
子字符串 。
b. 如果 candidate 是 searchValue ,返回
i 。
5. 返回 -1。
注 1
如果 searchValue 是空字符串且 fromIndex ≤ string 的长度,该算法返回
fromIndex 。空字符串实际上在字符串中的每个位置都能找到,包括在最后一个码位之后。
注 2
如果 fromIndex 加上 searchValue 的长度大于 string 的长度,该算法总是返回 -1。
6.1.5 符号类型(Symbol Type)
符号类型 是可以用作对象属性键的所有非字符串值的集合(6.1.7 )。
每个可能的符号值都是唯一且不可变的。
每个符号值不可变地持有一个关联的值,称为 [[Description]] ,它要么是 undefined ,要么是一个字符串值。
6.1.5.1 众所周知的符号(Well-Known Symbols)
众所周知的符号是本规范算法明确引用的内建符号值。它们通常用作属性的键,这些属性的值作为规范算法的扩展点。除非另有说明,否则众所周知的符号值在所有realm 中共享(9.3 )。
在本规范中,一个众所周知的符号用 @@name 的形式表示,其中“name”是表1 中列出的值之一。
表1: 众所周知的符号
规范名称
[[Description]]
值和用途
@@asyncIterator
"Symbol.asyncIterator"
一个方法,返回对象的默认异步迭代器。由for
-await
-of
语句的语义调用。
@@hasInstance
"Symbol.hasInstance"
一个方法,确定构造函数对象是否将某个对象识别为其实例之一。由instanceof
运算符的语义调用。
@@isConcatSpreadable
"Symbol.isConcatSpreadable"
一个布尔值属性,如果为true,表示对象应通过Array.prototype.concat
展平为其数组元素。
@@iterator
"Symbol.iterator"
一个方法,返回对象的默认迭代器。由for-of语句的语义调用。
@@match
"Symbol.match"
一个正则表达式方法,将正则表达式与字符串匹配。由String.prototype.match
方法调用。
@@matchAll
"Symbol.matchAll"
一个正则表达式方法,返回一个迭代器,该迭代器生成正则表达式与字符串匹配的所有结果。由String.prototype.matchAll
方法调用。
@@replace
"Symbol.replace"
一个正则表达式方法,替换字符串中的匹配子字符串。由String.prototype.replace
方法调用。
@@search
"Symbol.search"
一个正则表达式方法,返回匹配正则表达式的字符串中的索引。由String.prototype.search
方法调用。
@@species
"Symbol.species"
一个函数值属性,是用于创建派生对象的构造函数。
@@split
"Symbol.split"
一个正则表达式方法,在匹配正则表达式的索引处分割字符串。由String.prototype.split
方法调用。
@@toPrimitive
"Symbol.toPrimitive"
一个方法,将对象转换为相应的原始值。由ToPrimitive 抽象操作调用。
@@toStringTag
"Symbol.toStringTag"
一个字符串值属性,用于创建对象的默认字符串描述。由内建方法Object.prototype.toString
访问。
@@unscopables
"Symbol.unscopables"
一个对象值属性,其自身和继承的属性名称是从相关对象的with
环境绑定中排除的属性名称。
6.1.6 数字类型(Numeric Types)
ECMAScript 有两种内建的数字类型:Number 和 BigInt。以下抽象操作 定义在这些数字类型上。“结果”列显示返回类型,并指出某些操作调用是否可能返回异常完成 。
表2:数字类型操作
操作
示例源码
由评估 语义调用...
结果
Number::unaryMinus
-x
一元 -
运算符
Number
BigInt::unaryMinus
BigInt
Number::bitwiseNOT
~x
按位非运算符 (
~
)
Number
BigInt::bitwiseNOT
BigInt
Number::exponentiate
x ** y
幂运算符
和 Math.pow ( base ,
exponent )
Number
BigInt::exponentiate
要么是包含 BigInt 的正常完成,要么是抛出完成
Number::multiply
x * y
乘法运算符
Number
BigInt::multiply
BigInt
Number::divide
x / y
乘法运算符
Number
BigInt::divide
要么是包含 BigInt 的正常完成,要么是抛出完成
Number::remainder
x % y
乘法运算符
Number
BigInt::remainder
要么是包含 BigInt 的正常完成 ,要么是抛出完成
Number::add
x ++
++ x
x + y
后缀递增运算符 ,
前缀递增运算符 ,
和 加法运算符(+
)
Number
BigInt::add
BigInt
Number::subtract
x --
-- x
x - y
后缀递减运算符 ,
前缀递减运算符 ,
和 减法运算符(-
)
Number
BigInt::subtract
BigInt
Number::leftShift
x << y
左移位运算符(<<
)
Number
BigInt::leftShift
BigInt
Number::signedRightShift
x >> y
有符号右移位运算符(>>
)
Number
BigInt::signedRightShift
BigInt
Number::unsignedRightShift
x >>> y
The Unsigned Right
Shift Operator ( >>>
)
Number
BigInt::unsignedRightShift
a throw
completion
Number::lessThan
x < y
x > y
x <= y
x >= y
关系运算符 ,
via IsLessThan ( x , y ,
LeftFirst )
Boolean or undefined (for unordered inputs)
BigInt::lessThan
Boolean
Number::equal
x == y
x != y
x === y
x !== y
等值运算符 ,
via IsStrictlyEqual ( x ,
y )
Boolean
BigInt::equal
Number::sameValue
Object.is(x, y)
对象内部方法,
via SameValue ( x , y
) ,
测试精确的值相等性
Boolean
Number::sameValueZero
[x].includes(y)
Array、Map和Set方法,
via SameValueZero ( x ,
y ) ,
要测试值相等性,忽略 +0 𝔽 和
-0 𝔽
Boolean
Number::bitwiseAND
x & y
二进制按位运算符
Number
BigInt::bitwiseAND
BigInt
Number::bitwiseXOR
x ^ y
Number
BigInt::bitwiseXOR
BigInt
Number::bitwiseOR
x | y
Number
BigInt::bitwiseOR
BigInt
Number::toString
String(x)
许多表达式和内置函数, 经由 ToString ( argument
)
String
BigInt::toString
由于数值类型通常不能在不损失精度或截断的情况下相互转换,ECMAScript语言不提供这些类型之间的隐式转换。在调用需要另一种类型的函数时,程序员必须显式调用 Number
和
BigInt
函数进行类型转换。
注
ECMAScript 的早期和后续版本为某些运算符提供了隐式数值转换,这可能会损失精度或 截断 。这些遗留的隐式转换保留了向后兼容性,但不适用于
BigInt,以减少程序员错误的可能性,并为未来版本中的泛型 值类型 留出选项。
6.1.6.1 数字类型(The Number Type)
数字类型(Number type )具有精确的
18,437,736,874,454,810,627
(即 2** 64 - 2** 53 + 3 )个值,
表示双精度 64 位格式的 IEEE 754-2019 值,这些值按照 IEEE 二进制浮点算术标准规定。不同于 IEEE 标准的 9,007,199,254,740,990
(即 2** 53 -
2 )个“非数值(Not-a-Number)”值在 ECMAScript 中表示为单独的特殊值 NaN 。
(注意,NaN 值由程序表达式 NaN
产生。)在一些实现中,外部代码可能能够检测到各种不同的非数值,但这种行为是
实现定义的 ;
对于 ECMAScript 代码来说,所有的 NaN 值都是无法区分的。
注
在存储 Number 值到 ArrayBuffer(参见 25.1 )或
SharedArrayBuffer(参见 25.2 )后,可能观察到的位模式不一定与
ECMAScript 实现中使用的该 Number 值的内部表示相同。
还有另外两个特殊值,分别称为 positive Infinity 和 negative
Infinity 。为了简洁起见,在解释目的上,这些值也被表示为符号 +∞ 𝔽 和
-∞ 𝔽 ,分别。(注意,这两个无穷大的 Number 值由程序表达式 +Infinity
(或简单地
Infinity
)和 -Infinity
产生。)
其余的 18,437,736,874,454,810,624(即 2** 64
- 2** 53 )个值被称为 有限数 。其中一半是正数,一半是负数;对于每个 有限 的正数 Number 值,都有一个相应的具有相同数量级的负数值。
注意,这里有一个 positive zero 和一个 negative zero 。为了简洁起见,在解释目的上,这些值也被表示为符号
+0 𝔽 和 -0 𝔽 ,分别。(注意,这两个不同的零 Number 值由程序表达式
+0
(或简单地 0
)和 -0
产生。)
18,437,736,874,454,810,622(即 2** 64 -
2** 53 - 2 )个 有限 的非零值分为两种:
18,428,729,675,200,069,632(即 2** 64 -
2** 54 )个被规范化的值,具有以下形式:
s × m × 2** e
其中,s 可以是 1 或 -1,m 是一个 整数 ,在区间从 2** 52 (包含)到 2** 53 (不包含)之间,而
e 是一个 整数 ,在区间从 -1074 到 971 的
包含区间 内。
剩余的 9,007,199,254,740,990(即 2** 53 -
2 )个值是非规格化的,具有以下形式:
s × m × 2** e
其中,s 可以是 1 或 -1,m 是一个 整数 ,在区间从 0(不包含)到 2** 52 (不包含)之间,而 e 是 -1074。
注意,在 Number 类型中,所有不大于 2** 53 的正整数和负整数都可以表示。整数 0 在 Number
类型中有两种表示形式:+0 𝔽 和 -0 𝔽 。
一个 有限数
的“奇数有效尾数”指的是,如果它是非零的,并且用来表示它的 整数
m (以上述两种形式之一)是奇数。否则,它具有“偶数有效尾数”。
在本规范中,“ 表示为数值的 Number 值 for x ”这一短语表示选定以下方式的 Number 值。考虑所有的 Number
类型的 有限值 ,从中去除
-0 𝔽 ,并额外添加两个不可表示的值,即 2** 1024 (即
+1 × 2** 53 × 2** 971 )和 -2** 1024 (即 -1 × 2** 53 × 2** 971 )。选择这个集合中与 x
最接近的成员。如果集合中有两个值同样接近,则选择有效尾数为偶数的那个;为此,额外的两个值 2** 1024 和
-2** 1024
被认为具有偶数的有效尾数。最后,如果选择了 2** 1024 ,则用
+∞ 𝔽 替换它;如果选择了 -2** 1024 ,则用 -∞ 𝔽
替换它;如果选择了 +0 𝔽 ,则仅当 x < 0 时,用
-0 𝔽 替换它;否则使用选择的其他值而不变。结果就是 表示为数值的 Number 值 for
x 。(此过程与 IEEE 754-2019 roundTiesToEven
模式的行为完全对应。)
+∞
的 Number 值为 是
+∞ 𝔽 ,而 -∞ 的 Number 值为 是
-∞ 𝔽 。
一些 ECMAScript 运算符只处理特定范围内的 整数 ,比如从 -2** 31 到 2** 31 - 1 的 闭区间 或者从 0 到
2** 16 - 1 的 闭区间 。这些运算符接受 Number
类型的任何值,但首先将每个这样的值转换为预期范围内的 整数 值。请参阅 7.1 中的数值转换操作描述。
6.1.6.1.1 Number::unaryMinus ( x )
抽象操作 Number::unaryMinus 接受参数 x (一个 Number),并返回一个 Number。调用时执行以下步骤:
1. 如果 x 是 NaN ,则返回
NaN 。
2. 返回取反后的结果 x ;即具有相同大小但相反符号的 Number。
6.1.6.1.2 Number::bitwiseNOT ( x )
抽象操作 Number::bitwiseNOT 接受参数 x (一个 Number),并返回一个 整数型
Number 。调用时执行以下步骤:
1. 令 oldValue 为 ! ToInt32 (x )。
2. 返回对 oldValue 应用按位补码操作的结果。该结果的 数学值
正好可表示为一个32位的二进制补码字符串。
6.1.6.1.3 Number::exponentiate ( base , exponent )
抽象操作 Number::exponentiate 接受参数 base (一个 Number)和 exponent (一个 Number),并返回一个
Number。它返回一个 实现近似值 ,表示将
base 的 exponent 次幂的结果。调用时执行以下步骤:
1. 如果 exponent 是 NaN ,则返回
NaN 。
2. 如果 exponent 是 +0 𝔽 或
-0 𝔽 ,则返回 1 𝔽 。
3. 如果 base 是 NaN ,则返回
NaN 。
4. 如果 base 是 +∞ 𝔽 ,则
a. 如果 exponent >
+0 𝔽 ,则返回 +∞ 𝔽 。否则,返回
+0 𝔽 。
5. 如果 base 是 -∞ 𝔽 ,则
a. 如果 exponent >
+0 𝔽 ,那么
i. 如果 exponent 是奇数的 integral Number ,则返回
-∞ 𝔽 。否则,返回 +∞ 𝔽 。
b. 否则,
i. 如果 exponent 是奇数的 integral Number ,则返回
-0 𝔽 。否则,返回 +0 𝔽 。
6. 如果 base 是 +0 𝔽 ,则
a. 如果 exponent >
+0 𝔽 ,则返回 +0 𝔽 。否则,返回
+∞ 𝔽 。
7. 如果 base 是 -0 𝔽 ,则
a. 如果 exponent >
+0 𝔽 ,那么
i. 如果 exponent 是奇数的 integral Number ,则返回
-0 𝔽 。否则,返回 +0 𝔽 。
b. 否则,
i. 如果 exponent 是奇数的 integral Number ,则返回
-∞ 𝔽 。否则,返回 +∞ 𝔽 。
8. Assert : base 是有限数,并且不是
+0 𝔽 或 -0 𝔽 。
9. 如果 exponent 是 +∞ 𝔽 ,则
a. 如果 abs (ℝ (base )) > 1,则返回
+∞ 𝔽 。
b. 如果 abs (ℝ (base )) = 1,则返回
NaN 。
c. 如果 abs (ℝ (base )) < 1,则返回
+0 𝔽 。
10. 如果 exponent 是
-∞ 𝔽 ,则
a. 如果 abs (ℝ (base )) > 1,则返回
+0 𝔽 。
b. 如果 abs (ℝ (base )) = 1,则返回
NaN 。
c. 如果 abs (ℝ (base )) < 1,则返回
+∞ 𝔽 。
11. Assert : exponent 是 finite ,并且不是
+0 𝔽 或 -0 𝔽 。
12. 如果 base <
-0 𝔽 ,并且 exponent 不是一个 integral
Number ,则返回 NaN 。
13. 返回一个表示将 ℝ (base ) 的 ℝ (exponent ) 次幂的结果的
implementation-approximated
数值。
注
当 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 的乘积。调用时执行以下步骤:
1. 如果 x 是 NaN 或者 y 是
NaN ,则返回 NaN 。
2. 如果 x 是 +∞ 𝔽 或者
-∞ 𝔽 ,则
a. 如果 y 是 +0 𝔽 或者
-0 𝔽 ,则返回 NaN 。
b. 如果 y > +0 𝔽 ,则返回
x 。
c. 返回 -x 。
3. 如果 y 是 +∞ 𝔽 或者
-∞ 𝔽 ,则
a. 如果 x 是 +0 𝔽 或者
-0 𝔽 ,则返回 NaN 。
b. 如果 x > +0 𝔽 ,则返回
y 。
c. 返回 -y 。
4. 如果 x 是 -0 𝔽 ,则
a. 如果 y 是 -0 𝔽 或者
y
< -0 𝔽 ,则返回 +0 𝔽 。
b. 否则,返回 -0 𝔽 。
5. 如果 y 是 -0 𝔽 ,则
a. 如果 x
< -0 𝔽 ,则返回 +0 𝔽 。
b. 否则,返回 -0 𝔽 。
6. 返回 𝔽 (ℝ (x ) ×
ℝ (y ))。
注
6.1.6.1.5 Number::divide ( x , y )
抽象操作 Number::divide 接受参数 x (一个 Number)和 y (一个 Number),返回一个 Number。
它根据 IEEE
754-2019 二进制双精度算术规则执行除法,产生 x 除以 y 的商。
调用时执行以下步骤:
1. 如果 x 是 NaN 或者 y 是
NaN ,返回 NaN 。
2. 如果 x 是 +∞ 𝔽 或者
-∞ 𝔽 ,则
a. 如果 y 是 +∞ 𝔽 或者
-∞ 𝔽 ,返回 NaN 。
b. 如果 y 是 +0 𝔽 或者
y > +0 𝔽 ,返回 x 。
c. 返回 -x 。
3. 如果 y 是 +∞ 𝔽 ,则
a. 如果 x 是 +0 𝔽 或者
x > +0 𝔽 ,返回 +0 𝔽 。
否则,返回 -0 𝔽 。
4. 如果 y 是 -∞ 𝔽 ,则
a. 如果 x 是 +0 𝔽 或者
x > +0 𝔽 ,返回 -0 𝔽 。
否则,返回 +0 𝔽 。
5. 如果 x 是 +0 𝔽 或者
-0 𝔽 ,则
a. 如果 y 是 +0 𝔽 或者
-0 𝔽 ,返回 NaN 。
b. 如果 y > +0 𝔽 ,
返回 x 。
c. 返回 -x 。
6. 如果 y 是 +0 𝔽 ,则
a. 如果 x > +0 𝔽 ,
返回 +∞ 𝔽 。否则,返回 -∞ 𝔽 。
7. 如果 y 是 -0 𝔽 ,则
a. 如果 x > +0 𝔽 ,
返回 -∞ 𝔽 。否则,返回 +∞ 𝔽 。
8. 返回 𝔽 (ℝ (x ) /
ℝ (y )).
6.1.6.1.6 Number::remainder ( n , d )
抽象操作 Number::remainder 接受参数 n (一个 Number)和 d (一个 Number),返回一个
Number。
它返回其操作数的隐含除法的余数,其中 n 是被除数,d 是除数。调用时执行以下步骤:
1. 如果 n 是 NaN 或者 d 是
NaN ,返回 NaN 。
2. 如果 n 是 +∞ 𝔽 或者
-∞ 𝔽 ,返回 NaN 。
3. 如果 d 是 +∞ 𝔽 或者
-∞ 𝔽 ,返回 n 。
4. 如果 d 是 +0 𝔽 或者
-0 𝔽 ,返回 NaN 。
5. 如果 n 是 +0 𝔽 或者
-0 𝔽 ,返回 n 。
6. Assert : n 和 d 是
finite 的且非零。
7. 设 quotient 为 ℝ (n ) /
ℝ (d )。
8. 设 q 为 truncate (quotient )。
9. 设 r 为 ℝ (n ) - (ℝ (d ) ×
q )。
10. 如果 r = 0 并且 n <
-0 𝔽 ,返回 -0 𝔽 。
11. 返回 𝔽 (r )。
注1
在 C 和 C++ 中,取余运算符只接受整数操作数;在 ECMAScript 中,它也接受浮点操作数。
注2
浮点取余运算的结果与
%
运算符计算的“余数”操作不同,后者由
IEEE
754-2019 定义。
IEEE 754-2019
的“余数”操作从四舍五入的除法中计算余数,而不是截断的除法,因此其行为与通常的
整数 取余运算符不类似。
相反,ECMAScript 语言定义浮点操作的
%
以类似于 Java
整数 取余运算符的方式行为;这可以与 C 库函数
fmod 进行比较。
6.1.6.1.7 Number::add ( x , y )
抽象操作 Number::add 接受参数 x (一个 Number)和 y (一个 Number),返回一个
Number。它根据 IEEE
754-2019 二进制双精度算术的规则执行加法,生成其参数的和。调用时执行以下步骤:
1. 如果 x 是 NaN 或者 y 是
NaN ,返回 NaN 。
2. 如果 x 是 +∞ 𝔽 并且
y 是 -∞ 𝔽 ,返回 NaN 。
3. 如果 x 是 -∞ 𝔽 并且
y 是 +∞ 𝔽 ,返回 NaN 。
4. 如果 x 是 +∞ 𝔽 或者
-∞ 𝔽 ,返回 x 。
5. 如果 y 是 +∞ 𝔽 或者
-∞ 𝔽 ,返回 y 。
6. Assert : x 和 y 都是
有限的 。
7. 如果 x 是 -0 𝔽 并且
y 是 -0 𝔽 ,返回 -0 𝔽 。
8. 返回 𝔽 (ℝ (x ) +
ℝ (y ))。
注
6.1.6.1.8 Number::subtract ( x , y )
抽象操作 Number::subtract 接受参数 x (一个 Number)和 y (一个 Number),返回一个
Number。它执行减法运算,生成其操作数的差;x 是被减数,y 是减数。调用时执行以下步骤:
1. 返回 Number::add (x ,
Number::unaryMinus (y ))。
注
总是有 x - y
的结果与 x + (-y)
相同。
6.1.6.1.9 Number::leftShift ( x , y )
抽象操作 Number::leftShift 接受参数 x (一个 Number)和 y (一个 Number),返回一个整数
Number。调用时执行以下步骤:
1. 令 lnum 为 ! ToInt32 (x )。
2. 令 rnum 为 ! ToUint32 (y )。
3. 令 shiftCount 为 ℝ (rnum )
modulo 32。
4. 返回将 lnum 左移 shiftCount 位的结果。结果的
数学值 可准确表示为一个32位二进制补码位字符串。
6.1.6.1.10 Number::signedRightShift ( x , y )
抽象操作 Number::signedRightShift 接受参数 x (一个 Number)和 y (一个 Number),返回一个整数
Number。调用时执行以下步骤:
1. 令 lnum 为 ! ToInt32 (x )。
2. 令 rnum 为 ! ToUint32 (y )。
3. 令 shiftCount 为 ℝ (rnum )
modulo 32。
4. 返回将 lnum 右移 shiftCount
位并进行符号扩展的结果。最高有效位被传播。结果的
数学值 可准确表示为一个32位二进制补码位字符串。
6.1.6.1.11 Number::unsignedRightShift ( x , y )
抽象操作 Number::unsignedRightShift 接受参数 x (一个 Number)和 y (一个 Number),返回一个整数
Number。调用时执行以下步骤:
1. 令 lnum 为 ! ToUint32 (x )。
2. 令 rnum 为 ! ToUint32 (y )。
3. 令 shiftCount 为 ℝ (rnum )
modulo 32。
4. 返回将 lnum 右移 shiftCount
位并进行零填充的结果。空出的位将填充为零。结果的
数学值 可准确表示为一个32位无符号位字符串。
6.1.6.1.12 Number::lessThan ( x , y )
抽象操作 Number::lessThan 接受参数 x (一个 Number)和 y (一个 Number),返回一个布尔值或
undefined 。调用时执行以下步骤:
1. 如果 x 是 NaN ,则返回
undefined 。
2. 如果 y 是 NaN ,则返回
undefined 。
3. 如果 x 等于 y ,则返回 false 。
4. 如果 x 是 +0 𝔽 并且
y 是 -0 𝔽 ,则返回 false 。
5. 如果 x 是 -0 𝔽 并且
y 是 +0 𝔽 ,则返回 false 。
6. 如果 x 是 +∞ 𝔽 ,则返回
false 。
7. 如果 y 是 +∞ 𝔽 ,则返回
true 。
8. 如果 y 是 -∞ 𝔽 ,则返回
false 。
9. 如果 x 是 -∞ 𝔽 ,则返回
true 。
10. Assert : x 和 y 都是
finite 。
11. 如果 ℝ (x ) 小于 ℝ (y ),则返回
true 。否则,返回 false 。
6.1.6.1.13 Number::equal ( x , y )
抽象操作 Number::equal 接受参数 x (一个 Number)和 y (一个 Number),返回一个布尔值。调用时执行以下步骤:
1. 如果 x 是 NaN ,则返回
false 。
2. 如果 y 是 NaN ,则返回
false 。
3. 如果 x 等于 y ,则返回 true 。
4. 如果 x 是 +0 𝔽 并且
y 是 -0 𝔽 ,则返回 true 。
5. 如果 x 是 -0 𝔽 并且
y 是 +0 𝔽 ,则返回 true 。
6. 返回 false 。
6.1.6.1.14 Number::sameValue ( x , y )
抽象操作 Number::sameValue 接受参数 x (一个 Number)和 y (一个 Number),返回一个布尔值。调用时执行以下步骤:
1. 如果 x 是 NaN 并且 y 是
NaN ,则返回 true 。
2. 如果 x 是 +0 𝔽 并且
y 是 -0 𝔽 ,则返回 false 。
3. 如果 x 是 -0 𝔽 并且
y 是 +0 𝔽 ,则返回 false 。
4. 如果 x 等于 y ,则返回 true 。
5. 返回 false 。
6.1.6.1.15 Number::sameValueZero ( x , y )
抽象操作 Number::sameValueZero 接受参数 x (一个 Number)和 y (一个 Number),返回一个布尔值。调用时执行以下步骤:
1. 如果 x 是 NaN 并且 y 是
NaN ,则返回 true 。
2. 如果 x 是 +0 𝔽 并且
y 是 -0 𝔽 ,则返回 true 。
3. 如果 x 是 -0 𝔽 并且
y 是 +0 𝔽 ,则返回 true 。
4. 如果 x 等于 y ,则返回 true 。
5. 返回 false 。
6.1.6.1.16 Number::NumberBitwiseOp ( op , x ,
y )
抽象操作 Number::NumberBitwiseOp 接受参数 op (&
、^
或
|
)、x (一个 Number)和 y (一个 Number),返回一个 integral
Number 。调用时执行以下步骤:
1. 令 lnum 为 ! ToInt32 (x ).
2. 令 rnum 为 ! ToInt32 (y ).
3. 令 lbits 为表示 ℝ (lnum ) 的 32 位二进制补码位字符串。
4. 令 rbits 为表示 ℝ (rnum ) 的 32 位二进制补码位字符串。
5. 如果 op 是 &
,则
a. 令 result 为对 lbits 和 rbits
执行按位与操作的结果。
6. 否则,如果 op 是 ^
,则
a. 令 result 为对 lbits 和 rbits
执行按位异或(XOR)操作的结果。
7. 否则,
a. Assert :断言 op 是
|
。
b. 令 result 为对 lbits 和 rbits
执行按位或操作的结果。
8. 返回由 32 位二进制补码位字符串 result 表示的 Number value
for 的 integer 。
6.1.6.1.17 Number::bitwiseAND ( x , y )
抽象操作 Number::bitwiseAND 接受参数 x (一个 Number)和 y (一个 Number),返回一个 integral
Number 。调用时执行以下步骤:
1. 返回 NumberBitwiseOp (&
,
x , y ).
6.1.6.1.18 Number::bitwiseXOR ( x , y )
抽象操作 Number::bitwiseXOR 接受参数 x (一个 Number)和 y (一个 Number),返回一个 integral
Number 。调用时执行以下步骤:
1. 返回 NumberBitwiseOp (^
,
x , y ).
6.1.6.1.19 Number::bitwiseOR ( x , y )
抽象操作 Number::bitwiseOR 接受参数 x (一个 Number)和 y (一个 Number),返回一个 integral
Number 。调用时执行以下步骤:
1. 返回 NumberBitwiseOp (|
,
x , y ).
6.1.6.1.20 Number::toString ( x , radix )
抽象操作 Number::toString 接受参数 x (一个数字)和 radix (一个在 2 到 36 之间的整数),并返回一个字符串。它使用以
radix 为基数的进位制系统将 x 表示为字符串。使用基数 r 表示数字时所用的数字取自
"0123456789abcdefghijklmnopqrstuvwxyz" 的前 r 个字符。数值大小大于或等于
1 𝔽 的数字表示永远不会包含前导零。它在被调用时执行以下步骤:
1. 如果 x 是 NaN ,返回
"NaN" 。
2. 如果 x 是 +0 𝔽 或
-0 𝔽 ,返回 "0" 。
3. 如果 x < -0 𝔽 ,返回
字符串连接 的
"-" 和 Number::toString (-x ,
radix )。
4. 如果 x 是 +∞ 𝔽 ,返回
"Infinity" 。
5. 令
n 、k 和 s 为 整数 ,使得 k ≥
1,radix **( k - 1) ≤ s < radix ** k ,𝔽 (s ×
radix **( n - k ) ) 是 x ,并且 k 尽可能小。注意,k 是使用基数
radix 表示 s 的数字个数,s 不能被 radix 整除,并且 s
的最低有效位不一定由这些条件唯一确定。
6. 如果 radix ≠ 10 或 n 在 包含区间 从 -5 到 21,那么
a. 如果 n ≥ k ,那么
i. 返回 字符串连接 :
使用基数 radix 表示 s 的 k 位数字的代码单元
n - k 个代码单元 0x0030 (DIGIT ZERO)
b. 否则如果 n > 0,那么
i. 返回 字符串连接 :
使用基数 radix 表示 s 的最高有效 n 位数字的代码单元
代码单元 0x002E (FULL STOP)
使用基数 radix 表示 s 的剩余 k - n 位数字的代码单元
c. 否则,
i. 断言 :n ≤ 0。
ii. 返回 字符串连接 :
代码单元 0x0030 (DIGIT ZERO)
代码单元 0x002E (FULL STOP)
-n 个代码单元 0x0030 (DIGIT ZERO)
使用基数 radix 表示 s 的 k 位数字的代码单元
7. 注意:在这种情况下,输入将使用科学 E 表示法表示,例如 1.2e+3
。
8. 断言 :radix 是 10。
9. 如果 n < 0,那么
a. 令 exponentSign 为代码单元 0x002D (HYPHEN-MINUS)。
10. 否则,
a. 令 exponentSign 为代码单元 0x002B (PLUS SIGN)。
11. 如果 k = 1,那么
a. 返回 字符串连接 :
s 的单个数字的代码单元
代码单元 0x0065 (LATIN SMALL LETTER E)
exponentSign
十进制表示的 abs (n - 1)
12. 返回 字符串连接 :
十进制表示的 s 的最高有效位的代码单元
代码单元 0x002E (FULL STOP)
十进制表示的 s 的剩余 k - 1 位数字的代码单元
代码单元 0x0065 (LATIN SMALL LETTER E)
exponentSign
十进制表示的 abs (n - 1)
注 1
以下观察可能对实现有指导作用,但不是本标准规范性要求的一部分:
注 2
对于提供比上述规则更精确转换的实现,建议使用以下替代版本的步骤 5 作为指导:
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
值。如果有两个这样的可能值,选择偶数的那一个。注意,k 是使用基数 radix 表示 s 的数字个数,并且
s 不能被 radix 整除。
注 3
ECMAScript 的实现者可能会发现 David M. Gay 撰写的关于浮点数二进制到十进制转换的论文和代码很有用:
Gay, David M. 正确舍入的二进制-十进制和十进制-二进制转换。数值分析,手稿 90-10。AT&T 贝尔实验室(新泽西州默里山)。1990 年 11 月 30 日。
可在
http://ampl.com/REFS/abstracts.html#rounding
获取。
相关代码可在
http://netlib.sandia.gov/fp/dtoa.c 和
http://netlib.sandia.gov/fp/g_fmt.c 获取,并且可能在各个
netlib
镜像站点上找到。
6.1.6.2 BigInt 类型
BigInt 类型 表示一个 整数
值。该值可以是任意大小,并不限于特定的位宽。通常情况下,除非另有说明,操作旨在返回基于数学的精确答案。对于二进制操作,BigInt 表现为二进制补码字符串,负数被视为在其左侧有无限多的设置位。
6.1.6.2.1 BigInt::unaryMinus ( x )
抽象操作 BigInt::unaryMinus 接受参数 x (一个 BigInt)并返回一个 BigInt。它在被调用时执行以下步骤:
1. 如果 x 是 0 ℤ ,返回
0 ℤ 。
2. 返回 -x 。
6.1.6.2.2 BigInt::bitwiseNOT ( x )
抽象操作 BigInt::bitwiseNOT 接受参数 x (一个 BigInt)并返回一个 BigInt。
它返回 x 的按位取反。它在被调用时执行以下步骤:
1. 返回 -x - 1 ℤ 。
6.1.6.2.3 BigInt::exponentiate ( base , exponent )
抽象操作 BigInt::exponentiate 接受参数 base (一个 BigInt)和 exponent (一个 BigInt),并返回一个包含
BigInt 的正常完成或抛出完成。它在被调用时执行以下步骤:
1. 如果 exponent <
0 ℤ ,抛出一个 RangeError 异常。
2. 如果 base 是 0 ℤ 且
exponent 是 0 ℤ ,返回 1 ℤ 。
3. 返回 base 的 exponent 次方。
6.1.6.2.4 BigInt::multiply ( x , y )
抽象操作 BigInt::multiply 接受参数 x (一个 BigInt)和 y (一个 BigInt)并返回一个 BigInt。它在被调用时执行以下步骤:
1. 返回 x × y 。
注
即使结果的位宽比输入大得多,也会给出精确的数学答案。
6.1.6.2.5 BigInt::divide ( x , y )
抽象操作 BigInt::divide 接受参数 x (一个 BigInt)和 y (一个 BigInt),并返回一个包含 BigInt
的正常完成或抛出完成。它在被调用时执行以下步骤:
1. 如果 y 是 0 ℤ ,抛出一个
RangeError 异常。
2. 设 quotient 为 ℝ (x ) /
ℝ (y )。
3. 返回 ℤ (truncate (quotient ))。
6.1.6.2.6 BigInt::remainder ( n , d )
抽象操作 BigInt::remainder 接受参数 n (一个 BigInt)和 d (一个 BigInt),并返回一个 正常完成包含 一个
BigInt 或一个 抛出完成 。它在调用时执行以下步骤:
1. 如果 d 是 0 ℤ ,抛出一个
RangeError 异常。
2. 如果 n 是 0 ℤ ,返回
0 ℤ 。
3. 设 quotient 为 ℝ (n ) /
ℝ (d )。
4. 设 q 为 ℤ (截断 (quotient ))。
5. 返回 n - (d × q )。
注
结果的符号与被除数的符号相同。
6.1.6.2.7 BigInt::add ( x , y )
抽象操作 BigInt::add 接受参数 x (一个 BigInt)和 y (一个 BigInt)并返回一个 BigInt。它在被调用时执行以下步骤:
1. 返回 x + y 。
6.1.6.2.8 BigInt::subtract ( x , y )
抽象操作 BigInt::subtract 接受参数 x (一个 BigInt)和 y (一个 BigInt)并返回一个 BigInt。它在被调用时执行以下步骤:
1. 返回 x - y 。
6.1.6.2.9 BigInt::leftShift ( x , y )
抽象操作 BigInt::leftShift 接受参数 x (一个 BigInt)和 y (一个 BigInt)并返回一个 BigInt。它在被调用时执行以下步骤:
1. 如果 y < 0 ℤ ,则
a. 返回 ℤ (floor (ℝ (x ) / 2**( -ℝ (y ) ) )).
2. 返回 x × 2 ℤ ** y .
注
这里的语义应该等同于按位左移,将 BigInt 视为无限长度的二进制补码数字字符串。
6.1.6.2.10 BigInt::signedRightShift ( x , y )
抽象操作 BigInt::signedRightShift 接受参数 x (一个 BigInt)和 y (一个 BigInt)并返回一个
BigInt。它在被调用时执行以下步骤:
1. 返回 BigInt::leftShift (x ,
-y ).
6.1.6.2.11 BigInt::unsignedRightShift ( x , y )
抽象操作 BigInt::unsignedRightShift 接受参数 x (一个 BigInt)和 y (一个 BigInt)并返回一个 抛出完成记录 。它在被调用时执行以下步骤:
1. 抛出一个 TypeError 异常。
6.1.6.2.12 BigInt::lessThan ( x , y )
抽象操作 BigInt::lessThan 接受参数 x (一个 BigInt)和 y (一个 BigInt)并返回一个布尔值。它在被调用时执行以下步骤:
1. 如果 ℝ (x ) < ℝ (y ),返回
true ;否则返回 false 。
6.1.6.2.13 BigInt::equal ( x , y )
抽象操作 BigInt::equal 接受参数 x (一个 BigInt)和 y (一个 BigInt)并返回一个布尔值。它在被调用时执行以下步骤:
1. 如果 ℝ (x ) = ℝ (y ),
返回
true ;否则返回 false 。
6.1.6.2.14 BinaryAnd ( x , y )
抽象操作 BinaryAnd 接受参数 x (0 或 1)和 y (0 或 1)并返回 0 或 1。它在被调用时执行以下步骤:
1. 如果 x = 1 且 y = 1,返回 1。
2. 否则,返回 0。
6.1.6.2.15 BinaryOr ( x , y )
抽象操作 BinaryOr 接受参数 x (0 或 1)和 y (0 或 1)并返回 0 或 1。它在被调用时执行以下步骤:
1. 如果 x = 1 或 y = 1,返回 1。
2. 否则,返回 0。
6.1.6.2.16 BinaryXor ( x , y )
抽象操作 BinaryXor 接受参数 x (0 或 1)和 y (0 或 1)并返回 0 或 1。它在被调用时执行以下步骤:
1. 如果 x = 1 且 y = 0,返回 1。
2. 否则如果 x = 0 且 y = 1,返回 1。
3. 否则,返回 0。
6.1.6.2.17 BigInt位运算 ( op , x , y )
抽象操作 BigInt位运算 接受参数 op (&
、
^
或 |
)、x (一个 BigInt)和 y (一个 BigInt)并返回一个
BigInt。它在被调用时执行以下步骤:
1. 将 x 设置为 ℝ (x )。
2. 将 y 设置为 ℝ (y )。
3. 设 result 为 0。
4. 设 shift 为 0。
5. 重复,直到 (x = 0 或 x = -1) 和
(y = 0 或 y = -1),
a. 设 xDigit 为 x 取模 2。
b. 设 yDigit 为 y 取模 2。
c. 如果 op 是 &
,那么
i. 将 result 设置为 result + 2** shift × 按位与 (xDigit ,
yDigit )。
d. 否则如果 op 是 |
,那么
i. 将 result 设置为 result + 2** shift × 按位或 (xDigit ,
yDigit )。
e. 否则
i. 断言 : op 是
^
。
ii. 将 result 设置为 result + 2** shift × 按位异或 (xDigit ,
yDigit )。
f. 将 shift 设置为 shift + 1。
g. 将 x 设置为 (x - xDigit ) /
2。
h. 将 y 设置为 (y - yDigit ) /
2。
6. 如果 op 是 &
,那么
a. 设 tmp 为 按位与 (x
取模 2, y
取模 2)。
7. 否则如果 op 是 |
,那么
a. 设 tmp 为 按位或 (x
取模 2, y
取模 2)。
8. 否则
a. 断言 : op 是
^
。
b. 设 tmp 为 按位异或 (x
取模 2, y
取模 2)。
9. 如果 tmp ≠ 0,那么
a. 将 result 设置为 result - 2** shift 。
b. 注意:这扩展了符号位。
10. 返回 BigInt 值
for result 。
6.1.6.2.18 BigInt::bitwiseAND ( x , y )
抽象操作 BigInt::bitwiseAND 接受参数 x (一个 BigInt)和 y (一个 BigInt)并返回一个 BigInt。它在调用时执行以下步骤:
1. 返回 BigIntBitwiseOp (&
,
x , y )。
6.1.6.2.19 BigInt::bitwiseXOR ( x , y )
抽象操作 BigInt::bitwiseXOR 接受参数 x (一个 BigInt)和 y (一个 BigInt)并返回一个 BigInt。它在调用时执行以下步骤:
1. 返回 BigIntBitwiseOp (^
,
x , y )。
6.1.6.2.20 BigInt::bitwiseOR ( x , y )
抽象操作 BigInt::bitwiseOR 接受参数 x (一个 BigInt)和 y (一个 BigInt)并返回一个 BigInt。它在调用时执行以下步骤:
1. 返回 BigIntBitwiseOp (|
,
x , y )。
6.1.6.2.21 BigInt::toString ( x , radix )
抽象操作 BigInt::toString 接受参数 x (一个 BigInt)和 radix (一个在 2 到 36 之间的整数)并返回一个字符串。它使用基数
radix 将 x 表示为字符串。使用基数 r 表示 BigInt 的数字取自
"0123456789abcdefghijklmnopqrstuvwxyz" 的前 r 个码元。除了
0 ℤ 之外的 BigInt 表示永远不会包含前导零。它在调用时执行以下步骤:
1. 如果 x < 0 ℤ ,返回
字符串连接 的
"-" 和 BigInt::toString (-x ,
radix )。
2. 返回使用基数 radix 表示 x 的字符串值。
6.1.7 对象类型
每个 对象类型
的实例,也简称为“一个对象”,表示一个属性的集合。每个属性要么是一个数据属性,要么是一个访问器属性:
对象的属性使用属性键唯一标识。一个 属性键
要么是一个字符串,要么是一个符号。所有字符串和符号,包括空字符串,都可以作为属性键。一个 属性名 是一个 字符串 的属性键。
一个 整数索引 是一个
属性名 n ,使得
CanonicalNumericIndexString (n )
返回一个在 包含区间 从
+0 𝔽 到 𝔽 (2** 53 - 1) 内的 整数 。一个 数组索引 是一个 整数索引 n ,使得
CanonicalNumericIndexString (n )
返回一个在 包含区间 从
+0 𝔽 到 𝔽 (2** 32 - 2) 内的 整数 。
注
每个非负的 安全整数 都有一个对应的
整数索引 。除了 2** 32 - 1 之外的每个 32 位
无符号 整数 都有一个对应的
数组索引 。"-0" 既不是一个
整数索引 也不是
数组索引 。
属性键用于访问属性和它们的值。属性访问有两种类型:获取 和 设置 ,分别对应于值的检索和赋值。通过获取和设置访问的属性包括 自有属性 和
继承属性 。继承属性可能是关联对象的自有属性或继承属性。每个对象的自有属性必须具有与其他自有属性不同的键值。
所有对象在逻辑上都是属性的集合,但有多种形式的对象,它们的属性访问和操作语义不同。请参见 6.1.7.2
以了解多种形式的对象的定义。
此外,一些对象是可调用的;这些被称为函数或 函数对象 ,并在下面进一步描述。ECMAScript 中的所有函数都是
Object 类型的成员。
6.1.7.1 属性属性
属性用于在本规范中定义和解释对象属性的状态,如 表 3
所述。除非明确指定,每个属性的初始值为其默认值。
表 3: 对象属性的属性
属性名称
存在的属性类型
值域
默认值
描述
[[Value]]
数据属性
ECMAScript 语言值
undefined
通过获取属性访问检索到的值。
[[Writable]]
数据属性
布尔值
false
如果为 false ,尝试通过 ECMAScript 代码更改属性的 [[Value]] 属性将不会成功。
[[Get]]
访问器属性
对象或 undefined
undefined
如果值 是一个对象 ,它必须是一个 函数对象 。函数的 [[Call]] 内部方法(表
5 )在每次执行属性获取访问时被调用,不带参数。
[[Set]]
访问器属性
对象或 undefined
undefined
如果值 是一个对象 ,它必须是一个 函数对象 。函数的 [[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]] 的内部槽,它是一个 List 的
PrivateElements 。这个
List
表示对象的私有字段、方法和访问器的值。最初,它是一个空的 List 。
内部方法和内部槽在本规范中使用双括号 [[ ]] 括起来的名称进行标识。
表 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 | 属性描述符
返回该对象自身属性的 属性描述符 ,其键为
propertyKey ,或 undefined 如果没有这样的属性。
[[DefineOwnProperty]]
(propertyKey , 属性描述符 ) → Boolean
创建或修改自身属性,其键为 propertyKey ,具有 属性描述符 描述的状态。返回 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 属性键
返回一个 List ,其元素是对象的所有自身
属性键 。
表
5 总结了可能被调用为函数的对象支持的额外基本内部方法。一个 函数对象 是支持 [[Call]] 内部方法的对象。一个 构造函数 是支持 [[Construct]] 内部方法的对象。每个支持
[[Construct]] 的对象必须支持 [[Call]] ;也就是说,每个 构造函数
必须是一个 函数对象 。因此,一个 构造函数
也可以被称为 构造函数 函数 或 构造函数
函数对象 。
表 5: 函数对象的额外基本内部方法
内部方法
签名
描述
[[Call]]
(any , a List
of any ) → any
执行与此对象关联的代码。通过函数调用表达式调用。内部方法的参数是一个 this 值和一个 List ,其元素是通过调用表达式传递给函数的参数。实现此内部方法的对象是
可调用的 。
[[Construct]]
(a List
of any , Object) → Object
创建一个对象。通过 new
运算符或 super
调用调用。内部方法的第一个参数是一个 List ,其元素是
构造函数 调用或 super
调用的参数。第二个参数是最初应用 new
运算符的对象。实现此内部方法的对象称为 构造函数 。一个
函数对象 不一定是 构造函数 ,并且这些非 构造函数 函数对象 没有 [[Construct]] 内部方法。
普通对象和标准异域对象的基本内部方法的语义在第 10
条中指定。如果实现不支持异域对象的任何指定内部方法的使用,则必须在尝试时抛出 TypeError 异常。
6.1.7.3 基本内部方法的不变性
ECMAScript引擎中对象的内部方法必须符合下面指定的不变性列表。普通ECMAScript对象以及本规范中的所有标准异域对象 都保持这些不变性。ECMAScript代理对象通过在[[ProxyHandler]]
对象上调用的陷阱结果上进行运行时检查来保持这些不变性。
任何实现提供的异域对象 也必须为这些对象保持这些不变性。违反这些不变性可能导致ECMAScript代码行为不可预测并产生安全问题。然而,违反这些不变性绝不能损害实现的内存安全。
实现不得以任何方式允许绕过这些不变性,例如通过提供实现基本内部方法功能的替代接口而不强制执行其不变性。
定义:
内部方法的目标 是调用内部方法的对象。
如果目标对象的[[IsExtensible]] 内部方法返回false ,或者其[[PreventExtensions]] 内部方法返回true ,则该目标是不可扩展的 。
不存在的 属性是不可扩展目标对象上不存在的自有属性。
所有对SameValue 的引用均根据SameValue 算法的定义。
返回值:
任何内部方法返回的值必须是一个Completion
Record ,具有以下任一形式:
[[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 )
正常返回类型是Property
Descriptor 或Undefined。
如果返回值的类型是Property
Descriptor ,则返回值必须是一个完全填充的Property
Descriptor 。
如果P 被描述为不可配置、不可写的自有数据属性 ,所有未来对[[GetOwnProperty]] ( P )的调用必须返回Property
Descriptor ,其[[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。
[[DefineOwnProperty]] 必须返回false ,如果P 之前已被观察为目标对象的不可配置自有属性,除非:
P 是一个可写的数据属性 。一个不可配置的可写数据属性 可以被改变为一个不可配置的不可写数据属性 。
Desc 的所有属性与P 的属性相同SameValue 。
[[DefineOwnProperty]] ( P , Desc )
必须返回false ,如果目标对象是不可扩展的且P 是一个不存在的自有属性。也就是说,一个不可扩展的目标对象不能被扩展新的属性。
[[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]] ( )
正常返回类型是List 。
返回的List 不得包含任何重复条目。
返回的List 的每个元素的类型必须是String或Symbol。
返回的List 必须至少包含所有之前观察到的不可配置自有属性的键。
如果目标对象是不可扩展的,返回的List 必须仅包含目标对象的所有自有属性的键,这些属性可通过[[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 语言类型
的语义。规范类型包括引用(Reference)、列表(List) 、完成记录(Completion
Record) 、属性描述符(Property
Descriptor) 、环境记录(Environment Record) 、抽象闭包(Abstract Closure) 和 数据块(Data
Block) 。规范类型值是规范的产物,不一定对应于 ECMAScript 实现中的任何特定实体。规范类型值可用于描述 ECMAScript
表达式评估的中间结果,但这些值不能存储为对象的属性或 ECMAScript 语言变量的值。
6.2.1 枚举规范类型
枚举 是规范内部的值,不能直接从 ECMAScript 代码中观察到。枚举用
sans-serif 字体表示。例如,完成记录 的 [[Type]] 字段取值如 normal 、return 或
throw 。枚举除了名称外没有其他特征。枚举的名称仅用于区分其他枚举,并不暗示其在上下文中的使用或意义。
6.2.2 列表和记录规范类型
列表 类型用于解释参数列表的评估(参见 13.3.8 )在
new
表达式、函数调用和其他需要简单有序值列表的算法中。列表类型的值是包含各个值的列表元素的简单有序序列。这些序列可以是任意长度的。列表元素可以使用基于 0
的索引随机访问。为了表示方便,可以使用类似数组的语法来访问列表元素。例如,arguments [2] 是表示列表 arguments 的第 3 个元素的简写。
当算法迭代列表元素而不指定顺序时,使用的顺序是列表中元素的顺序。
为了在本规范中表示方便,可以使用字面量语法来表示新的列表值。例如,« 1, 2 » 定义了一个包含两个元素的列表值,每个元素初始化为特定值。一个新的空列表可以表示为 « »。
在本规范中,短语“列表连接
A 、B 、...”(其中每个参数是一个可能为空的列表)表示一个新列表值,其元素是每个参数(按顺序)的元素(按顺序)的连接。
记录 类型用于描述本规范算法中的数据聚合。记录类型值由一个或多个命名字段组成。每个字段的值是一个 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 的完成记录。
中断完成 指任何 [[Type]] 值为
break 的完成记录。
继续完成 指任何 [[Type]] 值为
continue 的完成记录。
返回完成 指任何 [[Type]] 值为
return 的完成记录。
抛出完成 指任何 [[Type]] 值为
throw 的完成记录。
异常完成 指任何 [[Type]] 值不是
normal 的完成记录。
某种类型的 正常完成包含 指 [[Value]] 字段中包含该类型值的正常完成。
本规范中定义的可调用对象仅返回正常完成或抛出完成。返回任何其他类型的完成记录被视为编辑错误。
实现定义 的可调用对象必须返回正常完成或抛出完成。
6.2.4.1 NormalCompletion ( value )
抽象操作 NormalCompletion 接受参数 value (任何值,除了 完成记录 )并返回一个
正常完成 。它在调用时执行以下步骤:
1. 返回 完成记录 {
[[Type]] : normal , [[Value]] :
value , [[Target]] :
empty }.
6.2.4.2 ThrowCompletion ( value )
抽象操作 ThrowCompletion 接受参数 value (一个 ECMAScript
语言值 )并返回一个 抛出完成 。它在调用时执行以下步骤:
1. 返回 完成记录 {
[[Type]] : throw , [[Value]] :
value , [[Target]] :
empty }.
6.2.4.3 UpdateEmpty ( completionRecord , value )
抽象操作 UpdateEmpty 接受参数 completionRecord (一个 完成记录 )和
value (任何值,除了 完成记录 )并返回一个
完成记录 。它在调用时执行以下步骤:
1. 断言 :如果 completionRecord
是 返回完成 或
抛出完成 ,则
completionRecord .[[Value]]
不是 empty 。
2. 如果 completionRecord .[[Value]]
不是 empty ,返回 ? completionRecord 。
3. 返回 完成记录 {
[[Type]] : completionRecord .[[Type]] , [[Value]] : value , [[Target]] :
completionRecord .[[Target]] }.
6.2.5 引用记录规范类型
引用记录 类型用于解释
delete
、typeof
、赋值运算符、super
关键字
和其他语言特性的行为。例如,赋值运算符的左操作数预期会产生一个引用记录。
引用记录是已解析的名称或属性绑定;其字段由 表 8 定义。
表 8: 引用记录 字段
字段名称
值
含义
[[Base]]
一个 ECMAScript
语言值 、一个
环境记录 或
unresolvable
持有绑定的值或 环境记录 。[[Base]] 为 unresolvable 表示绑定无法解析。
[[ReferencedName]]
字符串、符号或 私有名称
绑定的名称。如果 [[Base]] 值是 环境记录 ,则始终为字符串。
[[Strict]]
布尔值
true 如果引用记录源自 严格模式代码 ,false
否则。
[[ThisValue]]
一个 ECMAScript 语言值 或
empty
如果不是 empty ,则引用记录表示使用 super
关键字
表达的属性绑定;它被称为
超级引用记录 ,其 [[Base]]
值永远不会是 环境记录 。在这种情况下,[[ThisValue]] 字段保存创建引用记录时的 this 值。
以下 抽象操作
用于在本规范中操作引用记录:
6.2.5.1 IsPropertyReference ( V )
抽象操作 IsPropertyReference 接受参数 V (一个 引用记录 )并返回一个布尔值。它在调用时执行以下步骤:
1. 如果 V .[[Base]] 是
unresolvable ,返回 false 。
2. 如果 V .[[Base]] 是一个
环境记录 ,返回
false ;否则返回 true 。
6.2.5.2 IsUnresolvableReference ( V )
抽象操作 IsUnresolvableReference 接受参数 V (一个 引用记录 )并返回一个布尔值。当调用时,它执行以下步骤:
1. 如果 V .[[Base]] 是
unresolvable ,返回 true ;否则返回
false 。
6.2.5.3 IsSuperReference ( V )
抽象操作 IsSuperReference 接受参数 V (一个 引用记录 )并返回一个布尔值。当调用时,它执行以下步骤:
1. 如果 V .[[ThisValue]] 不是
empty ,返回 true ;否则返回
false 。
6.2.5.4 IsPrivateReference ( V )
抽象操作 IsPrivateReference 接受参数 V (一个 引用记录 )并返回一个布尔值。当调用时,它执行以下步骤:
1. 如果 V .[[ReferencedName]] 是
私有名称 ,返回
true ;否则返回 false 。
6.2.5.5 GetValue ( V )
抽象操作 GetValue 接受参数 V (一个 引用记录 或一个
ECMAScript 语言值 )并返回一个
正常完成包含 一个
ECMAScript 语言值 或一个
突然完成 。当调用时,它执行以下步骤:
1. 如果 V 不是一个 引用记录 ,返回
V 。
2. 如果 IsUnresolvableReference (V )
是 true ,抛出一个 ReferenceError 异常。
3. 如果 IsPropertyReference (V )
是 true ,那么
a. 令 baseObj 为
? ToObject (V .[[Base]] )。
b. 如果 IsPrivateReference (V )
是 true ,那么
i. 返回 ? PrivateGet (baseObj , V .[[ReferencedName]] )。
c. 返回 ? baseObj .[[Get]] (V .[[ReferencedName]] ,
GetThisValue (V ))。
4. 否则,
a. 令 base 为 V .[[Base]] 。
b. 断言 :base 是一个
环境记录 。
c. 返回 ? base .GetBindingValue (V .[[ReferencedName]] , V .[[Strict]] )(见
9.1 )。
注
在步骤 3.a 中可能创建的对象在上述抽象操作和
普通对象 [[Get]] 内部方法之外不可访问。实现可能会选择避免实际创建该对象。
6.2.5.6 PutValue ( V , W )
抽象操作 PutValue 接受参数 V (一个 引用记录 或一个
ECMAScript 语言值 )和
W (一个 ECMAScript 语言值 )并返回一个
正常完成包含
unused 或一个 突然完成 。当调用时,它执行以下步骤:
1. 如果 V 不是一个 引用记录 ,抛出一个
ReferenceError 异常。
2. 如果 IsUnresolvableReference (V )
是 true ,那么
a. 如果 V .[[Strict]] 是
true ,抛出一个 ReferenceError 异常。
b. 令 globalObj 为 GetGlobalObject ()。
c. 执行 ? Set (globalObj , V .[[ReferencedName]] , W , false )。
d. 返回 unused 。
3. 如果 IsPropertyReference (V )
是 true ,那么
a. 令 baseObj 为
? ToObject (V .[[Base]] )。
b. 如果 IsPrivateReference (V )
是 true ,那么
i. 返回 ? PrivateSet (baseObj , V .[[ReferencedName]] , W )。
c. 令 succeeded 为 ? baseObj .[[Set]] (V .[[ReferencedName]] ,
W , GetThisValue (V ))。
d. 如果 succeeded 是 false 且
V .[[Strict]] 是 true ,抛出一个
TypeError 异常。
e. 返回 unused 。
4. 否则,
a. 令 base 为 V .[[Base]] 。
b. 断言 :base 是一个
环境记录 。
c. 返回 ? base .SetMutableBinding (V .[[ReferencedName]] , W , V .[[Strict]] )(见 9.1 )。
注
在步骤 3.a 中可能创建的对象在上述抽象操作和
普通对象 [[Set]] 内部方法之外不可访问。实现可能会选择避免实际创建该对象。
6.2.5.7 GetThisValue ( V )
抽象操作GetThisValue接受参数V (一个引用记录 )并返回一个ECMAScript语言值 。它在调用时执行以下步骤:
1. 断言 :IsPropertyReference (V )
是true 。
2. 如果IsSuperReference (V )
是true ,返回V .[[ThisValue]] ;否则返回V .[[Base]] 。
6.2.5.8 InitializeReferencedBinding ( V , W )
抽象操作InitializeReferencedBinding接受参数V (一个引用记录 )和W (一个ECMAScript语言值 )并返回一个正常完成包含
未使用 或一个突然完成 。它在调用时执行以下步骤:
1. 断言 :IsUnresolvableReference (V )
是false 。
2. 设base 为V .[[Base]] 。
3. 断言 :base 是一个环境记录 。
4. 返回
? base .InitializeBinding(V .[[ReferencedName]] ,
W )。
6.2.5.9 MakePrivateReference ( baseValue ,
privateIdentifier )
抽象操作MakePrivateReference接受参数baseValue (一个ECMAScript语言值 )和privateIdentifier (一个字符串)并返回一个引用记录 。它在调用时执行以下步骤:
1. 设privEnv 为运行执行上下文 的PrivateEnvironment。
2. 断言 :privEnv 不是null 。
3. 设privateName 为ResolvePrivateIdentifier (privEnv ,
privateIdentifier )。
4. 返回引用记录 {
[[Base]] : baseValue , [[ReferencedName]] :
privateName , [[Strict]] :
true , [[ThisValue]] :
empty }。
6.2.6 属性描述符规范类型
属性描述符类型用于解释对象属性属性的操作和具体化。属性描述符是一个记录 ,包含零个或多个字段,其中每个字段的名称是一个属性名称,其值是对应的属性值,如6.1.7.1 中所指定。本规范中用于标记属性描述符记录的架构名称是“PropertyDescriptor”。
属性描述符值可以根据某些字段的存在或使用进一步分类为数据属性描述符和访问器属性描述符。数据属性描述符是包含名为[[Value]] 或[[Writable]] 的字段的描述符。访问器属性描述符是包含名为[[Get]] 或[[Set]] 的字段的描述符。任何属性描述符都可能包含名为[[Enumerable]] 和[[Configurable]] 的字段。属性描述符值不能同时是数据属性描述符和访问器属性描述符;然而,它可以既不是(在这种情况下,它是一个通用属性描述符)。一个完全填充的属性描述符 是访问器属性描述符或数据属性描述符,并且具有表3 中定义的所有对应字段。
以下抽象操作 用于在本规范中操作属性描述符值:
6.2.6.1 IsAccessorDescriptor ( Desc )
抽象操作IsAccessorDescriptor接受参数Desc (一个属性描述符 或undefined )并返回一个布尔值。它在调用时执行以下步骤:
1.
如果Desc 是undefined ,返回false 。
2. 如果Desc 有[[Get]] 字段,返回true 。
3. 如果Desc 有[[Set]] 字段,返回true 。
4. 返回false 。
6.2.6.2 IsDataDescriptor ( Desc )
抽象操作IsDataDescriptor接受参数Desc (一个属性描述符 或undefined )并返回一个布尔值。它在调用时执行以下步骤:
1.
如果Desc 是undefined ,返回false 。
2. 如果Desc 有[[Value]] 字段,返回true 。
3. 如果Desc 有[[Writable]] 字段,返回true 。
4. 返回false 。
6.2.6.3 IsGenericDescriptor ( Desc )
抽象操作IsGenericDescriptor接受参数Desc (一个属性描述符 或undefined )并返回一个布尔值。它在调用时执行以下步骤:
1.
如果Desc 是undefined ,返回false 。
2. 如果IsAccessorDescriptor (Desc )
是true ,返回false 。
3. 如果IsDataDescriptor (Desc )
是true ,返回false 。
4. 返回true 。
6.2.6.4 FromPropertyDescriptor ( Desc )
抽象操作FromPropertyDescriptor接受参数Desc (一个属性描述符 或undefined )并返回一个对象或undefined 。它在调用时执行以下步骤:
1.
如果Desc 是undefined ,返回undefined 。
2. 设obj 为OrdinaryObjectCreate (%Object.prototype% )。
3. 断言 :obj 是一个可扩展的普通对象 ,没有自己的属性。
4. 如果Desc 有[[Value]] 字段,则
a. 执行! CreateDataPropertyOrThrow (obj ,
"value" , Desc .[[Value]] )。
5. 如果Desc 有[[Writable]] 字段,则
a. 执行! CreateDataPropertyOrThrow (obj ,
"writable" , Desc .[[Writable]] )。
6. 如果Desc 有[[Get]] 字段,则
a. 执行! CreateDataPropertyOrThrow (obj ,
"get" , Desc .[[Get]] )。
7. 如果Desc 有[[Set]] 字段,则
a. 执行! CreateDataPropertyOrThrow (obj ,
"set" , Desc .[[Set]] )。
8. 如果Desc 有[[Enumerable]] 字段,则
a. 执行! CreateDataPropertyOrThrow (obj ,
"enumerable" , Desc .[[Enumerable]] )。
9. 如果Desc 有[[Configurable]] 字段,则
a. 执行! CreateDataPropertyOrThrow (obj ,
"configurable" , Desc .[[Configurable]] )。
10. 返回obj 。
6.2.6.5 ToPropertyDescriptor ( Obj )
抽象操作ToPropertyDescriptor接受参数Obj (一个ECMAScript语言值 )并返回一个正常完成包含 一个属性描述符 或一个抛出完成 。它在调用时执行以下步骤:
1. 如果Obj 不是一个对象 ,抛出一个TypeError 异常。
2. 设desc 为一个新属性描述符 ,最初没有字段。
3. 设hasEnumerable 为? HasProperty (Obj , "enumerable" )。
4. 如果hasEnumerable 是true ,则
a. 设enumerable 为ToBoolean (?
Get (Obj , "enumerable" ))。
b. 设desc .[[Enumerable]] 为enumerable 。
5. 设hasConfigurable 为? HasProperty (Obj ,
"configurable" )。
6. 如果hasConfigurable 是true ,则
a. 设configurable 为ToBoolean (?
Get (Obj , "configurable" ))。
b. 设desc .[[Configurable]] 为configurable 。
7. 设hasValue 为? HasProperty (Obj , "value" )。
8. 如果hasValue 是true ,则
a. 设value 为? Get (Obj , "value" )。
b. 设desc .[[Value]] 为value 。
9. 设hasWritable 为? HasProperty (Obj , "writable" )。
10. 如果hasWritable 是true ,则
a. 设writable 为ToBoolean (?
Get (Obj , "writable" ))。
b. 设desc .[[Writable]] 为writable 。
11. 设hasGet 为? HasProperty (Obj , "get" )。
12. 如果hasGet 是true ,则
a. 设getter 为? Get (Obj , "get" )。
b. 如果IsCallable (getter )是false 且getter 不是undefined ,抛出一个TypeError 异常。
c. 设desc .[[Get]] 为getter 。
13. 设hasSet 为? HasProperty (Obj , "set" )。
14. 如果hasSet 是true ,则
a. 设setter 为? Get (Obj , "set" )。
b. 如果IsCallable (setter )是false 且setter 不是undefined ,抛出一个TypeError 异常。
c. 设desc .[[Set]] 为setter 。
15. 如果desc 有[[Get]] 字段或desc 有[[Set]] 字段,则
a. 如果desc 有[[Value]] 字段或desc 有[[Writable]] 字段,抛出一个TypeError 异常。
16. 返回desc 。
6.2.6.6 CompletePropertyDescriptor ( Desc )
抽象操作CompletePropertyDescriptor接受参数Desc (一个属性描述符 )并返回未使用 。它在调用时执行以下步骤:
1. 设like 为记录 { [[Value]] : undefined , [[Writable]] :
false , [[Get]] :
undefined , [[Set]] : undefined , [[Enumerable]] : false , [[Configurable]] : false }。
2. 如果IsGenericDescriptor (Desc )
是true 或IsDataDescriptor (Desc )
是true ,则
a. 如果Desc 没有[[Value]] 字段,设Desc .[[Value]] 为like .[[Value]] 。
b. 如果Desc 没有[[Writable]] 字段,设Desc .[[Writable]] 为like .[[Writable]] 。
3. 否则
a. 如果Desc 没有[[Get]] 字段,设Desc .[[Get]] 为like .[[Get]] 。
b. 如果Desc 没有[[Set]] 字段,设Desc .[[Set]] 为like .[[Set]] 。
4. 如果Desc 没有[[Enumerable]] 字段,设Desc .[[Enumerable]] 为like .[[Enumerable]] 。
5. 如果Desc 没有[[Configurable]] 字段,设Desc .[[Configurable]] 为like .[[Configurable]] 。
6. 返回未使用 。
6.2.7 环境记录规范类型
环境记录 类型用于解释嵌套函数和块中的名称解析行为。这种类型及其操作在9.1 中定义。
6.2.8 抽象闭包规范类型
抽象闭包规范类型用于引用算法步骤以及一组值。抽象闭包通过函数应用风格调用,例如closure (arg1 , arg2 )。与抽象操作 类似,调用抽象闭包时执行其描述的算法步骤。
在创建抽象闭包的算法步骤中,值通过“捕获”动词后跟别名列表来捕获。当创建抽象闭包时,它会捕获创建时与每个别名关联的值。在指定抽象闭包被调用时要执行的算法步骤中,每个捕获的值通过用于捕获该值的别名来引用。
如果抽象闭包返回一个完成记录 ,该完成记录 必须是正常完成 或抛出完成 。
抽象闭包作为其他算法的一部分内联创建,如下例所示。
1. 设addend 为41。
2. 设closure 为一个新抽象闭包 ,参数为(x ),捕获addend ,并在调用时执行以下步骤:
a. 返回x + addend 。
3. 设val 为closure (1)。
4. 断言 :val 为42。
6.2.9 数据块
数据块规范类型用于描述一个独特且可变的字节大小(8位)数值序列。字节值是一个整数 ,范围在包含区间 从0到255。
数据块值在创建时具有固定数量的字节,每个字节的初始值为0。
为了在本规范中表示方便,可以使用类似数组的语法来访问数据块值的各个字节。这种表示法将数据块值呈现为从0开始的整数索引 字节序列。例如,如果db 是一个5字节的数据块值,则db [2]可以用来访问其第3个字节。
驻留在可以被多个代理 并发引用的内存中的数据块被称为共享数据块 。共享数据块具有地址无关 的身份(用于测试共享数据块值的相等性):它不绑定到任何进程中块映射到的虚拟地址,而是绑定到块表示的内存位置集合。两个数据块相等仅当它们包含的位置集合相等;否则,它们不相等,并且它们包含的位置集合的交集为空。最后,共享数据块可以与数据块区分开来。
共享数据块的语义通过共享数据块事件 由内存模型 定义。抽象操作 引入共享数据块事件 ,并作为评估语义和内存模型 的事件语义之间的接口。事件形成一个候选执行 ,内存模型在此基础上充当过滤器。请查阅内存模型 以获取完整语义。
共享数据块事件 由记录 建模,定义在内存模型 中。
以下抽象操作 用于在本规范中操作数据块值:
6.2.9.1 CreateByteDataBlock ( size )
抽象操作CreateByteDataBlock接受参数size (一个非负整数 )并返回一个正常完成包含 一个数据块 或一个抛出完成 。它在调用时执行以下步骤:
1. 如果size > 2** 53 - 1,抛出一个RangeError 异常。
2. 设db 为一个新数据块 值,包含size 字节。如果无法创建这样的数据块 ,抛出一个RangeError 异常。
3. 将db 的所有字节设置为0。
4. 返回db 。
6.2.9.2 CreateSharedByteDataBlock ( size )
抽象操作 CreateSharedByteDataBlock 接受参数 size (一个非负的
整数 )
并返回一个 正常完成记录 包含一个
共享数据块 或一个 抛出完成记录 。它在被调用时执行以下步骤:
1. 令 db 为一个由 size 字节组成的新 共享数据块 值。如果无法创建这样的
共享数据块 ,则抛出一个
RangeError 异常。
2. 令 execution 为 周围代理 的 代理记录 的 [[CandidateExecution]] 字段。
3. 令 eventsRecord 为 execution .[[EventsRecords]] 的 代理事件记录 ,其 [[AgentSignifier]] 为 代理标识符 ()。
4. 令 zero 为 « 0 »。
5. 对于 db 的每个索引 i ,执行以下步骤:
a. 将 写共享内存
{ [[Order]] : init , [[NoTear]] : true , [[Block]] :
db , [[ByteIndex]] : i , [[ElementSize]] : 1, [[Payload]] :
zero } 追加到 eventsRecord .[[EventList]] 。
6. 返回 db 。
6.2.9.3 CopyDataBlockBytes ( toBlock , toIndex ,
fromBlock , fromIndex , count )
抽象操作 CopyDataBlockBytes 接受参数 toBlock (一个 数据块 或一个 共享数据块 ),
toIndex (一个非负的 整数 ),fromBlock (一个
数据块 或一个 共享数据块 ),fromIndex (一个非负的
整数 ),和
count (一个非负的 整数 )并返回
unused 。它在被调用时执行以下步骤:
1. 断言 :fromBlock 和
toBlock 是不同的值。
2. 令 fromSize 为 fromBlock 中的字节数。
3. 断言 :fromIndex +
count ≤ fromSize 。
4. 令 toSize 为 toBlock 中的字节数。
5. 断言 :toIndex +
count ≤ toSize 。
6. 重复,当 count > 0 时,执行以下步骤:
a. 如果 fromBlock 是一个 共享数据块 ,则
i. 令 execution 为 周围代理 的 代理记录 的 [[CandidateExecution]] 字段。
ii. 令 eventsRecord 为 execution .[[EventsRecords]] 的 代理事件记录 ,其 [[AgentSignifier]] 为 代理标识符 ()。
iii. 令 bytes 为一个 列表 ,其唯一元素是一个不确定选择的
字节值 。
iv. 注意:在实现中,bytes 是底层硬件上非原子读指令的结果。这种不确定性是
内存模型
的语义描述,用于描述具有弱一致性硬件的可观察行为。
v. 令 readEvent 为 读共享内存
{ [[Order]] : unordered , [[NoTear]] : true , [[Block]] :
fromBlock , [[ByteIndex]] : fromIndex , [[ElementSize]] : 1 }。
vi. 将 readEvent 追加到
eventsRecord .[[EventList]] 。
vii. 将 选择值记录 { [[Event]] : readEvent , [[ChosenValue]] : bytes } 追加到 execution .[[ChosenValues]] 。
viii. 如果 toBlock 是一个 共享数据块 ,则
1. 将 写共享内存
{ [[Order]] : unordered , [[NoTear]] : true , [[Block]] : toBlock , [[ByteIndex]] :
toIndex , [[ElementSize]] : 1, [[Payload]] :
bytes } 追加到 eventsRecord .[[EventList]] 。
ix. 否则,
1. 将 toBlock [toIndex ] 设置为
bytes [0]。
b. 否则,
i. 断言 :toBlock 不是一个
共享数据块 。
ii. 将 toBlock [toIndex ] 设置为
fromBlock [fromIndex ]。
c. 将 toIndex 设置为 toIndex + 1。
d. 将 fromIndex 设置为 fromIndex + 1。
e. 将 count 设置为 count - 1。
7. 返回 unused 。
6.2.10 私有元素规范类型
私有元素类型是一个 记录 ,用于规范私有类字段、方法和访问器。尽管
属性描述符
不适用于私有元素,但私有字段的行为类似于不可配置、不可枚举、可写的 数据属性 ,私有方法的行为类似于不可配置、不可枚举、不可写的 数据属性 ,私有访问器的行为类似于不可配置、不可枚举的 访问器属性 。
私有元素类型的值是 记录 值,其字段由
表 9 定义。这些值被称为 私有元素 。
表 9: 私有元素
字段
字段名称
[[Kind]] 字段值
值
含义
[[Key]]
所有
一个 私有名称
字段、方法或访问器的名称。
[[Kind]]
所有
field , method , 或 accessor
元素的种类。
[[Value]]
field 和 method
一个 ECMAScript 语言值
字段的值。
[[Get]]
accessor
一个 函数对象 或
undefined
私有访问器的 getter。
[[Set]]
accessor
一个 函数对象 或
undefined
私有访问器的 setter。
6.2.11 类字段定义记录规范类型
类字段定义类型是一个 记录 ,用于规范类字段。
类字段定义类型的值是 记录 值,其字段由
表 10 定义。这些值被称为 类字段定义记录 。
表 10: 类字段定义记录
字段
字段名称
值
含义
[[Name]]
一个 私有名称 、字符串或符号
字段的名称。
[[Initializer]]
一个 ECMAScript 函数对象 或
empty
字段的初始化器(如果有)。
6.2.12 私有名称
私有名称规范类型用于描述一个全局唯一的值(不同于任何其他私有名称,即使它们在其他方面无法区分),该值表示私有类元素(字段、方法或访问器)的键。每个私有名称都有一个关联的不可变 [[Description]] ,它是一个 字符串 值。私有名称可以通过
PrivateFieldAdd 或 PrivateMethodOrAccessorAdd
安装在任何 ECMAScript 对象上,然后使用 PrivateGet 和 PrivateSet 进行读取或写入。
6.2.13 类静态块定义记录规范类型
类静态块定义记录是一个 记录
值,用于封装类静态初始化块的可执行代码。
类静态块定义记录的字段列在 表 11 中。
表 11: 类静态块定义记录
字段
字段名称
值
含义
[[BodyFunction]]
一个 ECMAScript 函数对象
在类静态初始化期间调用的 函数对象 。
7 抽象操作
这些操作不是 ECMAScript 语言的一部分;它们在这里仅用于帮助规范 ECMAScript 语言的语义。其他更专业的 抽象操作
定义在本规范的其他部分。
7.1 类型转换
ECMAScript 语言在需要时隐式执行自动类型转换。为了阐明某些结构的语义,定义了一组转换 抽象操作 。这些转换
抽象操作
是多态的;它们可以接受任何 ECMAScript 语言类型
的值。但其他规范类型不与这些操作一起使用。
ECMAScript 语言中的 BigInt 类型
没有隐式转换;程序员必须显式调用 BigInt 来从其他类型转换值。
7.1.1 ToPrimitive ( input [ , preferredType ] )
抽象操作 ToPrimitive 接受参数 input (一个 ECMAScript 语言值 )和可选参数
preferredType (string 或
number )并返回一个 正常完成包含 一个
ECMAScript 语言值 或一个
抛出完成 。它将其
input 参数转换为非 对象类型 。如果对象能够转换为多种原始类型,它可能会使用可选提示
preferredType 来优先考虑该类型。它在被调用时执行以下步骤:
1. 如果 input 是一个对象 ,
then
a. 令 exoticToPrim 为 ? GetMethod (input , @@toPrimitive )。
b. 如果 exoticToPrim 不是
undefined ,
then
i. 如果 preferredType 不存在,则
1. 令 hint 为 "default" 。
ii. 否则如果 preferredType 是
string ,则
1. 令 hint 为 "string" 。
iii. 否则,
1. 断言 :
preferredType 是 number 。
2. 令 hint 为 "number" 。
iv. 令 result 为 ? Call (exoticToPrim , input , «
hint »)。
v. 如果 result 不是一个对象 ,返回
result 。
vi. 抛出一个 TypeError 异常。
c. 如果 preferredType 不存在,令
preferredType 为 number 。
d. 返回 ? OrdinaryToPrimitive (input ,
preferredType )。
2. 返回 input 。
注
当 ToPrimitive 被调用时不带提示时,它的行为通常类似于提示为 number 。然而,对象可以通过定义 @@toPrimitive
方法来覆盖这种行为。在本规范中,只有日期对象(参见 21.4.4.45 )和符号对象(参见
20.4.3.5 )覆盖了默认的
ToPrimitive 行为。日期对象将没有提示视为提示为 string 。
7.1.1.1 OrdinaryToPrimitive ( O , hint )
抽象操作 OrdinaryToPrimitive 接受参数 O (一个对象)和 hint
(string 或 number )并返回一个 正常完成包含 一个
ECMAScript 语言值 或一个
抛出完成 。它在被调用时执行以下步骤:
1. 如果 hint 是 string ,则
a. 令 methodNames 为 «
"toString" , "valueOf" »。
2. 否则,
a. 令 methodNames 为 «
"valueOf" ,
"toString" »。
3. 对于 methodNames 的每个元素 name ,执行
a. 令 method 为 ? Get (O , name )。
b. 如果 IsCallable (method )
is true ,则
i. 令 result 为 ? Call (method , O )。
ii. 如果 result 不是一个对象 ,返回
result 。
4. 抛出一个 TypeError 异常。
7.1.2 ToBoolean ( argument )
抽象操作 ToBoolean 接受参数 argument (一个 ECMAScript
语言值 )并返回一个布尔值。它将 argument 转换为布尔类型。
它在被调用时执行以下步骤:
1. 如果 argument 是一个布尔值 ,返回
argument 。
2. 如果 argument
是以下之一:undefined 、null 、+0 𝔽 、-0 𝔽 、NaN 、0 ℤ
或空字符串,返回 false 。
3. 注意:这一步在 B.3.6.1 中被替换。
4. 返回 true 。
7.1.3 ToNumeric ( value )
抽象操作 ToNumeric 接受参数 value (一个 ECMAScript 语言值 )并返回一个
正常完成包含 一个数字或
BigInt,或一个 抛出完成 。它返回
value 转换为数字或 BigInt。它在被调用时执行以下步骤:
1. 令 primValue 为 ? ToPrimitive (value , number )。
2. 如果 primValue 是一个
BigInt ,返回 primValue 。
3. 返回 ? ToNumber (primValue )。
7.1.4 ToNumber ( argument )
抽象操作 ToNumber 接受参数 argument (一个 ECMAScript 语言值 )并返回一个
正常完成包含 一个数字或一个
抛出完成 。它将
argument 转换为数字类型。它在被调用时执行以下步骤:
1. 如果 argument 是一个数字 ,返回
argument 。
2. 如果 argument 是符号或 BigInt,抛出一个
TypeError 异常。
3. 如果 argument 是 undefined ,返回
NaN 。
4. 如果 argument 是 null 或
false ,返回 +0 𝔽 。
5. 如果 argument 是 true ,返回
1 𝔽 。
6. 如果 argument 是一个字符串 ,返回
StringToNumber (argument )。
7. 断言 :argument 是一个对象 。
8. 令 primValue 为 ? ToPrimitive (argument ,
number )。
9. 断言 :primValue 不是一个对象 。
10. 返回 ? 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 (一个字符串)并返回一个数字。
当调用时,它执行以下步骤:
1. 令 text 为 StringToCodePoints (str ).
2. 令 literal 为 ParseText (text ,
StringNumericLiteral ).
3. 如果 literal 是一个 List
的错误,返回 NaN .
4. 返回 StringNumericValue
的 literal .
7.1.4.1.2 运行时语义:StringNumericValue
语法导向操作 StringNumericValue
不接受参数并返回一个数字。
注
它在以下产生式上分段定义:
StringNumericLiteral
::: StrWhiteSpace opt
1. 返回 +0 𝔽 。
StringNumericLiteral
:::
StrWhiteSpace opt
StrNumericLiteral
StrWhiteSpace opt
1. 返回 StringNumericValue
的 StrNumericLiteral 。
StrNumericLiteral
::: NonDecimalIntegerLiteral
1. 返回 𝔽 (MV of NonDecimalIntegerLiteral )。
StrDecimalLiteral
:::
-
StrUnsignedDecimalLiteral
1. 令 a 为 StringNumericValue
的 StrUnsignedDecimalLiteral 。
2. 如果 a 是 +0 𝔽 ,返回
-0 𝔽 。
3. 返回 -a 。
StrUnsignedDecimalLiteral
::: Infinity
1. 返回 +∞ 𝔽 。
StrUnsignedDecimalLiteral
:::
DecimalDigits
.
DecimalDigits opt
ExponentPart opt
1. 令 a 为第一个 DecimalDigits 的 MV。
2. 如果第二个 DecimalDigits 存在,则
a. 令 b 为第二个 DecimalDigits 的 MV。
b. 令 n 为第二个
DecimalDigits 的代码点数。
3. 否则,
a. 令 b 为 0。
b. 令 n 为 0。
4. 如果 ExponentPart 存在,令
e 为 ExponentPart 的 MV。否则,令
e 为 0。
5. 返回 RoundMVResult ((a
+ (b × 10** -n )) × 10** e )。
StrUnsignedDecimalLiteral
:::
.
DecimalDigits
ExponentPart opt
1. 令 b 为 DecimalDigits 的 MV。
2. 如果 ExponentPart 存在,令
e 为 ExponentPart 的 MV。否则,令
e 为 0。
3. 令 n 为 DecimalDigits 的代码点数。
4. 返回 RoundMVResult (b
× 10**( e - n ) )。
StrUnsignedDecimalLiteral
:::
DecimalDigits
ExponentPart opt
1. 令 a 为 DecimalDigits 的 MV。
2. 如果 ExponentPart 存在,令
e 为 ExponentPart 的 MV。否则,令
e 为 0。
3. 返回 RoundMVResult (a
× 10** e )。
7.1.4.1.3 RoundMVResult ( n )
抽象操作 RoundMVResult 接受参数 n (一个 mathematical
value )并返回一个数字。它以一种实现定义 的方式将 n
转换为数字。对于此抽象操作的目的,如果一个数字不是零,或者它的左边和右边都有非零数字,则该数字是重要的。对于此抽象操作的目的,“表示的 mathematical
value ”是“十进制表示”的逆。它执行以下步骤:
1. 如果 n 的十进制表示有 20 个或更少的有效数字,返回 𝔽 (n )。
2. 令 option1 为结果的 mathematical
value ,其中 n 的十进制表示中第 20 位之后的每个有效数字都被替换为 0。
3. 令 option2 为结果的 mathematical
value ,其中 n 的十进制表示中第 20 位之后的每个有效数字都被替换为 0,然后在第 20 位处递增(必要时进位)。
4. 令 chosen 为 实现定义 的
option1 或 option2 的选择。
5. 返回 𝔽 (chosen )。
7.1.5 ToIntegerOrInfinity ( argument )
抽象操作 ToIntegerOrInfinity 接受参数 argument (一个 ECMAScript 语言
值 )并返回一个 正常
完成包含 一个 整数 、+∞ 或 -∞,或一个 抛出
完成 。它将 argument 转换为一个 整数 ,表示其
数值的小数部分被截断,或者在数值为无穷大时转换为 +∞ 或 -∞。它在调用时执行以下步骤:
1. 令 number 为 ? ToNumber (argument ).
2. 如果 number 是 NaN 、
+0 𝔽 或 -0 𝔽 ,返回 0.
3. 如果 number 是 +∞ 𝔽 ,
返回
+∞.
4. 如果 number 是 -∞ 𝔽 ,
返回
-∞.
5. 返回 truncate (ℝ (number )).
注
𝔽 (ToIntegerOrInfinity(
x ))
永远不会返回
-0 𝔽 对于任何
x 的值。小数部分的截断
是在将
x 转换为
数学
值 之后进行的。
7.1.6 ToInt32 ( argument )
抽象操作 ToInt32 接受参数 argument (一个 ECMAScript 语言
值 )并返回一个 正常
完成包含 一个 整数 Number 或一个 抛出
完成 。它将 argument 转换为 2** 32 个
整数
Number 值之一,范围在 包含区间 从 𝔽 (-2** 31 ) 到 𝔽 (2** 31 - 1)。它在调用时执行以下步骤:
1. 令 number 为 ? ToNumber (argument ).
2. 如果 number 不是 有限 或
number 是 +0 𝔽 或 -0 𝔽 ,
返回 +0 𝔽 .
3. 令 int 为 truncate (ℝ (number )).
4. 令 int32bit 为 int modulo 2** 32 .
5. 如果 int32bit ≥ 2** 31 ,返回 𝔽 (int32bit - 2** 32 );否则返回 𝔽 (int32bit ).
注
根据上述 ToInt32 的定义:
ToInt32 抽象操作是幂等的:如果应用于其产生的结果,第二次应用不会改变该值。
ToInt32(ToUint32 (x )) 与
ToInt32(x ) 对于所有 x 的值是相同的。(为了保持这一特性,+∞ 𝔽 和
-∞ 𝔽 被映射到
+0 𝔽 。)
ToInt32 将 -0 𝔽 映射到 +0 𝔽 。
7.1.7 ToUint32 ( argument )
抽象操作 ToUint32 接受参数 argument (一个 ECMAScript 语言
值 )并返回一个 正常
完成包含 一个 整数 Number 或一个 抛出
完成 。它将 argument 转换为 2** 32 个
整数
Number 值之一,范围在 包含区间 从
+0 𝔽 到 𝔽 (2** 32 - 1)。它在调用时执行以下步骤:
1. 令 number 为 ? ToNumber (argument ).
2. 如果 number 不是 有限 或
number 是 +0 𝔽 或 -0 𝔽 ,
返回 +0 𝔽 .
3. 令 int 为 truncate (ℝ (number )).
4. 令 int32bit 为 int modulo 2** 32 .
5. 返回 𝔽 (int32bit ).
注
根据上述 ToUint32 的定义:
步骤 5 是 ToUint32 和 ToInt32
之间的唯一区别。
ToUint32 抽象操作是幂等的:如果应用于其产生的结果,第二次应用不会改变该值。
ToUint32(ToInt32 (x )) 与
ToUint32(x ) 对于所有 x 的值是相同的。(为了保持这一特性,+∞ 𝔽 和
-∞ 𝔽 被映射到
+0 𝔽 。)
ToUint32 将 -0 𝔽 映射到 +0 𝔽 。
7.1.8 ToInt16 ( argument )
抽象操作 ToInt16 接受参数 argument (一个 ECMAScript 语言值 )并返回一个
正常完成 ,其中包含一个
整数 ,或者一个 抛出完成 。它将
argument 转换为 2** 16 个 整数 值之一,这些值位于 闭区间 𝔽 (-2** 15 ) 到 𝔽 (2** 15 - 1) 之间。调用时,它执行以下步骤:
1. 令 number 为 ? ToNumber (argument )。
2. 如果 number 不是 有限的 或者 number 是
+0 𝔽 或 -0 𝔽 ,返回
+0 𝔽 。
3. 令 int 为 截断 (ℝ (number ))。
4. 令 int16bit 为 int 模 2** 16 。
5. 如果 int16bit ≥ 2** 15 ,返回 𝔽 (int16bit - 2** 16 );否则返回 𝔽 (int16bit )。
7.1.9 ToUint16 ( argument )
抽象操作 ToUint16 接受参数 argument (一个 ECMAScript 语言值 )并返回一个
正常完成 ,其中包含一个
整数 ,或者一个 抛出完成 。它将
argument 转换为 2** 16 个 整数 值之一,这些值位于 闭区间
+0 𝔽 到 𝔽 (2** 16 - 1) 之间。调用时,它执行以下步骤:
1. 令 number 为 ? ToNumber (argument )。
2. 如果 number 不是 有限的 或者 number 是
+0 𝔽 或 -0 𝔽 ,返回
+0 𝔽 。
3. 令 int 为 截断 (ℝ (number ))。
4. 令 int16bit 为 int
模
2** 16 。
5. 返回 𝔽 (int16bit )。
注
根据上述 ToUint16 的定义:
在第 4 步中将 2** 16 替换为 2** 32 是
ToUint32 和 ToUint16 唯一的区别。
ToUint16 将 -0 𝔽 映射为 +0 𝔽 。
7.1.10 ToInt8 ( argument )
抽象操作 ToInt8 接受参数 argument (一个 ECMAScript 语言值 ),并返回一个
正常完成 ,其中包含一个
整数 ,或者一个 抛出完成 。它将
argument 转换为 2** 8 个 整数 值之一,这些值位于 闭区间
-128 𝔽 到 127 𝔽 之间。调用时,它执行以下步骤:
1. 令 number 为 ? ToNumber (argument )。
2. 如果 number 不是 有限的 或者 number 是
+0 𝔽 或 -0 𝔽 ,返回
+0 𝔽 。
3. 令 int 为 截断 (ℝ (number ))。
4. 令 int8bit 为 int 模 2** 8 。
5. 如果 int8bit ≥ 2** 7 ,返回 𝔽 (int8bit - 2** 8 );否则返回 𝔽 (int8bit )。
7.1.11 ToUint8(argument )
抽象操作ToUint8接受参数argument (一个ECMAScript语言值 ),并返回一个包含整数Number 的正常完成 或一个抛出完成 。它将argument 转换为从+0 𝔽 到255 𝔽 的28 个整数Number 值中的一个,这些值在包含区间 内。当被调用时,执行以下步骤:
1. 令number 为 ToNumber (argument )。
2. 如果number 不是有限 的,或number 是+0 𝔽 或-0 𝔽 ,则返回+0 𝔽 。
3. 令int 为 截断 (ℝ (number ))。
4. 令int8bit 为 int 模 28 。
5. 返回 𝔽 (int8bit )。
7.1.12 ToUint8Clamp ( argument )
抽象操作 ToUint8Clamp 接受参数 argument (一个 ECMAScript
语言值 ),并返回一个 正常完成记录,包含 一个
整数 或一个 抛出完成记录 。它将
argument 钳制和四舍五入到 28 个 整数 值之一,在 闭区间 从
+0 𝔽 到 255 𝔽 之间。调用时执行以下步骤:
1. 令 number 为 ? ToNumber (argument )。
2. 如果 number 是 NaN ,返回
+0 𝔽 。
3. 令 mv 为 number
的扩展数学值 。
4. 令 clamped 为 将 mv 钳制在 0 和 255 之间的结果。
5. 令 f 为 floor (clamped )。
6. 如果 clamped < f + 0.5,返回 𝔽 (f )。
7. 如果 clamped > f + 0.5,返回 𝔽 (f + 1)。
8. 如果 f 是偶数,返回 𝔽 (f )。否则,返回 𝔽 (f + 1)。
注
与大多数其他 ECMAScript 整数 转换操作不同,ToUint8Clamp
是四舍五入而不是截断非整数值。它还使用“向偶数舍入”的中点舍入方法,这与 Math.round
的“向上舍入”方法不同。
7.1.13 ToBigInt ( argument )
抽象操作 ToBigInt 接受参数 argument (一个 ECMAScript 语言值 ),并返回一个
正常完成记录,包含 一个
BigInt 或一个 抛出完成记录 。它将
argument 转换为 BigInt 值,或者在需要从 Number 隐式转换时抛出错误。调用时执行以下步骤:
1. 令 prim 为 ? ToPrimitive (argument , number )。
2. 返回 prim 在 表 12 中对应的值。
表 12: BigInt 转换
参数类型
结果
Undefined
抛出 TypeError 异常。
Null
抛出 TypeError 异常。
Boolean
如果 prim 是 true ,返回 1n
;如果 prim 是
false ,返回 0n
。
BigInt
返回 prim 。
Number
抛出 TypeError 异常。
String
1. 令 n 为 StringToBigInt (prim )。
2. 如果 n 是 undefined ,抛出
SyntaxError 异常。
3. 返回 n 。
Symbol
抛出 TypeError 异常。
7.1.14 StringToBigInt ( str )
抽象操作 StringToBigInt 接受参数 str (一个字符串)并返回一个 BigInt 或 undefined 。调用时执行以下步骤:
1. 令 text 为 StringToCodePoints (str )。
2. 令 literal 为 ParseText (text , StringIntegerLiteral )。
3. 如果 literal 是一个 错误列表 ,返回
undefined 。
4. 令 mv 为 literal 的 MV。
5. 断言 :mv 是一个 整数 。
6. 返回 ℤ (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 或一个 抛出完成记录 。它将
argument 转换为 264 个 BigInt 值之一,在 闭区间 从 ℤ (-263 ) 到 ℤ (263 -
1)。调用时执行以下步骤:
1. 令 n 为 ? ToBigInt (argument )。
2. 令 int64bit 为 ℝ (n ) 取模 264 。
3. 如果 int64bit ≥ 263 ,返回 ℤ (int64bit -
264 );否则返回 ℤ (int64bit )。
7.1.16 ToBigUint64 ( argument )
抽象操作 ToBigUint64 接受参数 argument (一个 ECMAScript
语言值 ),并返回一个 正常完成记录,包含 一个
BigInt 或一个 抛出完成记录 。它将
argument 转换为 264 个 BigInt 值之一,在 闭区间 从
0 ℤ 到 ℤ (264 - 1)。调用时执行以下步骤:
1. 令 n 为 ? ToBigInt (argument )。
2. 令 int64bit 为 ℝ (n ) 取模 264 。
3. 返回 ℤ (int64bit )。
7.1.17 ToString ( argument )
抽象操作 ToString 接受参数 argument (一个 ECMAScript 语言值 ),并返回一个
正常完成记录,包含
一个字符串或一个 抛出完成记录 。它将
argument 转换为一个字符串类型的值。调用时执行以下步骤:
1. 如果 argument 是一个字符串 ,返回
argument 。
2. 如果 argument 是一个符号 ,抛出一个
TypeError 异常。
3. 如果 argument 是 undefined ,返回
"undefined" 。
4. 如果 argument 是 null ,返回
"null" 。
5. 如果 argument 是 true ,返回
"true" 。
6. 如果 argument 是 false ,返回
"false" 。
7. 如果 argument 是一个数字 ,返回
Number::toString (argument ,
10)。
8. 如果 argument 是一个
BigInt ,返回 BigInt::toString (argument ,
10)。
9. 断言 :argument 是一个对象 。
10. 令 primValue 为 ? ToPrimitive (argument , string )。
11. 断言 :primValue 不是一个对象 。
12. 返回 ? ToString (primValue )。
7.1.18 ToObject ( argument )
抽象操作 ToObject 接受参数 argument (一个 ECMAScript 语言值 ),并返回一个
正常完成记录,包含
一个对象或一个 抛出完成记录 。它根据
表 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 。参见
21.2 获取 BigInt 对象的描述。
Object
返回 argument 。
7.1.19 ToPropertyKey ( argument )
抽象操作 ToPropertyKey 接受参数 argument (一个 ECMAScript
语言值 ),并返回一个 正常完成记录,包含 一个
属性键 或一个 抛出完成记录 。它将
argument 转换为可以用作 属性键 的值。调用时执行以下步骤:
1. 令 key 为 ? ToPrimitive (argument , string )。
2. 如果 key 是一个符号 ,那么
a. 返回 key 。
3. 返回 ! ToString (key )。
7.1.20 ToLength ( argument )
抽象操作 ToLength 接受参数 argument (一个 ECMAScript 语言值 ),并返回一个
正常完成记录,包含 一个
整数 或一个 抛出完成记录 。它将
argument 钳制和截取为一个适合作为 类数组对象 长度的 整数 。调用时执行以下步骤:
1. 令 len 为 ? ToIntegerOrInfinity (argument )。
2. 如果 len ≤ 0,返回 +0 𝔽 。
3. 返回 𝔽 (min (len ,
253 - 1))。
7.1.21 CanonicalNumericIndexString ( argument )
抽象操作 CanonicalNumericIndexString 接受参数 argument (一个字符串)并返回一个数字或 undefined 。如果
argument 是 "-0" 或完全匹配某个数字值 n 的 ToString (n )
的结果,则返回相应的数字值。否则,它返回 undefined 。调用时执行以下步骤:
1. 如果 argument 是 "-0" ,返回
-0 𝔽 。
2. 令 n 为 ! ToNumber (argument )。
3. 如果 ! ToString (n ) 是
argument ,返回 n 。
4. 返回 undefined 。
一个规范数字字符串 是任何使 CanonicalNumericIndexString
抽象操作不返回 undefined 的字符串值。
7.1.22 ToIndex ( value )
抽象操作 ToIndex 接受参数 value (一个 ECMAScript 语言值 ),并返回一个
正常完成记录,包含 一个非负
整数 或一个
抛出完成记录 。它将
value 转换为一个 整数 ,并返回该 整数 ,如果它是非负的并且对应于一个 整数索引 。否则,它会抛出一个异常。调用时执行以下步骤:
1. 令 integer 为 ? ToIntegerOrInfinity (value )。
2. 如果 integer 不在从 0 到 253 - 1 的 闭区间 内,抛出一个
RangeError 异常。
3. 返回 integer 。
7.2 测试和比较操作
7.2.1 RequireObjectCoercible ( argument )
抽象操作 RequireObjectCoercible 接受参数 argument (一个 ECMAScript
语言值 ),并返回一个 正常完成记录,包含 一个
ECMAScript 语言值 或一个
抛出完成记录 。如果
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 语言值 ),并返回一个
正常完成记录,包含
一个布尔值或一个 抛出完成记录 。调用时执行以下步骤:
1. 如果 argument 不是一个对象 ,返回
false 。
2. 如果 argument 是一个 数组异质对象 ,返回
true 。
3. 如果 argument 是一个 代理异质对象 ,那么
a. 执行 ? ValidateNonRevokedProxy (argument )。
b. 令 proxyTarget 为 argument .[[ProxyTarget]] 。
c. 返回 ? IsArray (proxyTarget )。
4. 返回 false 。
7.2.3 IsCallable ( argument )
抽象操作 IsCallable 接受参数 argument (一个 ECMAScript
语言值 ),并返回一个布尔值。它确定 argument 是否是一个具有 [[Call]]
内部方法的可调用函数。调用时执行以下步骤:
1. 如果 argument 不是一个对象 ,返回
false 。
2. 如果 argument 具有 [[Call]] 内部方法,返回
true 。
3. 返回 false 。
7.2.4 IsConstructor ( argument )
抽象操作 IsConstructor 接受参数 argument (一个 ECMAScript
语言值 ),并返回一个布尔值。它确定 argument 是否是一个具有 [[Construct]]
内部方法的 函数对象 。调用时执行以下步骤:
1. 如果 argument 不是一个对象 ,返回
false 。
2. 如果 argument 具有 [[Construct]]
内部方法,返回 true 。
3. 返回 false 。
7.2.5 IsExtensible ( O )
抽象操作 IsExtensible 接受参数 O (一个对象),并返回一个 正常完成记录,包含
一个布尔值或一个 抛出完成记录 。它用于确定是否可以向
O 添加其他属性。调用时执行以下步骤:
1. 返回 ? O .[[IsExtensible]] ()。
7.2.6 IsIntegralNumber ( argument )
抽象操作 IsIntegralNumber 接受参数 argument (一个 ECMAScript
语言值 ),并返回一个布尔值。它确定 argument 是否是一个 有限的 整数 值。调用时执行以下步骤:
1. 如果 argument 不是一个数字 ,返回
false 。
2. 如果 argument 不是 有限的 ,返回
false 。
3. 如果 truncate (ℝ (argument )) ≠
ℝ (argument ), 返回
false 。
4. 返回 true 。
7.2.7 IsPropertyKey ( argument )
抽象操作 IsPropertyKey 接受参数 argument (一个 ECMAScript
语言值 ),并返回一个布尔值。它确定 argument 是否是一个可以用作 属性键 的值。调用时执行以下步骤:
1. 如果 argument 是一个字符串 ,返回
true 。
2. 如果 argument 是一个符号 ,返回
true 。
3. 返回 false 。
7.2.8 IsRegExp ( argument )
抽象操作 IsRegExp 接受参数 argument (一个 ECMAScript 语言值 ),并返回一个
正常完成记录,包含
一个布尔值或一个 抛出完成记录 。调用时执行以下步骤:
1. 如果 argument 不是一个对象 ,返回
false 。
2. 令 matcher 为 ? Get (argument , @@match )。
3. 如果 matcher 不是 undefined ,返回 ToBoolean (matcher )。
4. 如果 argument 具有 [[RegExpMatcher]] 内部槽,返回 true 。
5. 返回 false 。
7.2.9 静态语义:IsStringWellFormedUnicode ( string )
抽象操作 IsStringWellFormedUnicode 接受参数 string (一个字符串),并返回一个布尔值。它将 string 解释为一系列 UTF-16
编码的代码点,如 6.1.4
中描述,并确定它是否是一个 格式良好 的 UTF-16
序列。调用时执行以下步骤:
1. 令 len 为 string 的长度。
2. 令 k 为 0。
3. 重复,直到 k < len ,
a. 令 cp 为 CodePointAt (string ,
k )。
b. 如果 cp .[[IsUnpairedSurrogate]] 为 true ,返回 false 。
c. 将 k 设置为 k + cp .[[CodeUnitCount]] 。
4. 返回 true 。
7.2.10 SameValue ( x , y )
抽象操作 SameValue 接受参数 x (一个 ECMAScript 语言值 )和
y (一个 ECMAScript
语言值 ),并返回一个布尔值。它确定这两个参数是否是相同的值。调用时执行以下步骤:
1. 如果 Type (x )
不是 Type (y ),返回
false 。
2. 如果 x 是一个数字 ,那么
a. 返回 Number::sameValue (x ,
y )。
3. 返回 SameValueNonNumber (x ,
y )。
注
这个算法不同于 IsStrictlyEqual 算法,因为它将所有
NaN 值视为等价,并区分 +0 𝔽 和
-0 𝔽 。
7.2.11 SameValueZero ( x , y )
抽象操作 SameValueZero 接受参数 x (一个 ECMAScript 语言值 )和
y (一个 ECMAScript
语言值 ),并返回一个布尔值。它确定这两个参数是否是相同的值(忽略 +0 𝔽 和
-0 𝔽 之间的差异)。调用时执行以下步骤:
1. 如果 Type (x )
不是 Type (y ),返回
false 。
2. 如果 x 是一个数字 ,那么
a. 返回 Number::sameValueZero (x ,
y )。
3. 返回 SameValueNonNumber (x ,
y )。
注
SameValueZero 与 SameValue 的唯一区别是它将
+0 𝔽 和 -0 𝔽 视为等价。
7.2.12 SameValueNonNumber ( x , y )
抽象操作 SameValueNonNumber 接受参数 x (一个 ECMAScript
语言值 ,但不是数字)和 y (一个 ECMAScript
语言值 ,但不是数字),并返回一个布尔值。调用时执行以下步骤:
1. 断言 :Type (x )
是 Type (y )。
2. 如果 x 是 null 或
undefined ,返回 true 。
3. 如果 x 是一个
BigInt ,那么
a. 返回 BigInt::equal (x ,
y )。
4. 如果 x 是一个字符串 ,那么
a. 如果 x 和 y 具有相同的长度并且在相同的位置具有相同的代码单元,返回
true ;否则,返回 false 。
5. 如果 x 是一个布尔值 ,那么
a. 如果 x 和 y 都是 true 或都为
false ,返回 true ;否则,返回 false 。
6. 注意:所有其他 ECMAScript
语言值 通过身份进行比较。
7. 如果 x 是 y ,返回 true ;否则,返回
false 。
注 1
出于阐述目的,即使没有必要,也会在此算法中单独处理某些情况。
注 2
7.2.13 IsLessThan ( x , y , LeftFirst )
抽象操作 IsLessThan 接受参数 x (一个 ECMAScript
语言值 ),y (一个 ECMAScript 语言值 ),和
LeftFirst (一个布尔值),并返回一个 正常完成包含 一个布尔值或
undefined ,或一个 抛出完成 。它提供了比较
x <
y 的语义,返回 true ,false ,或
undefined (表示至少一个操作数是 NaN )。LeftFirst 标志用于控制对 x
和 y 进行可能具有可见副作用的操作的顺序。这是必要的,因为 ECMAScript 指定了从左到右的表达式求值顺序。如果
LeftFirst 是 true ,x 参数对应于出现在 y 参数对应表达式左侧的表达式。如果
LeftFirst
是
false ,情况相反,必须在 x 之前对 y 进行操作。它在调用时执行以下步骤:
1. 如果 LeftFirst 是 true ,则
a. 令 px 为 ? ToPrimitive (x , number ).
b. 令 py 为 ? ToPrimitive (y , number ).
2. 否则
a. 注意:需要反转求值顺序以保持从左到右的求值。
b. 令 py 为 ? ToPrimitive (y , number ).
c. 令 px 为 ? ToPrimitive (x , number ).
3. 如果 px 是一个
字符串 且 py 是一个
字符串 ,则
a. 令 lx 为 px 的长度。
b. 令 ly 为 py 的长度。
c. 对于每个 整数 i 使得 0 ≤
i < min (lx , ly ),
按升序进行以下操作
i. 令 cx 为 px 中索引 i 处的代码单元数值。
ii. 令 cy 为 py 中索引 i 处的代码单元数值。
iii. 如果 cx < cy ,返回
true .
iv. 如果 cx > cy ,返回
false .
d. 如果 lx < ly ,返回
true 。否则,返回 false .
4. 否则
a. 如果 px 是一个
BigInt 且 py 是一个
字符串 ,则
i. 令 ny 为 StringToBigInt (py ).
ii. 如果 ny 是 undefined ,返回
undefined .
iii. 返回 BigInt::lessThan (px ,
ny ).
b. 如果 px 是一个
字符串 且 py 是一个
BigInt ,则
i. 令 nx 为 StringToBigInt (px ).
ii. 如果 nx 是 undefined ,返回
undefined .
iii. 返回 BigInt::lessThan (nx ,
py ).
c. 注意:因为 px 和 py 是原始值,求值顺序不重要。
d. 令 nx 为 ? ToNumeric (px ).
e. 令 ny 为 ? ToNumeric (py ).
f. 如果 Type (nx )
是 Type (ny ),则
i. 如果 nx 是一个
数字 ,则
1. 返回 Number::lessThan (nx ,
ny ).
ii. 否则
1. 断言 :nx
是一个
BigInt .
2. 返回 BigInt::lessThan (nx ,
ny ).
g. 断言 :nx 是一个
BigInt 且 ny 是一个
数字 ,或 nx 是一个
数字 且 ny 是一个
BigInt .
h. 如果 nx 或 ny 是 NaN ,
返回 undefined .
i. 如果 nx 是 -∞ 𝔽 或
ny 是 +∞ 𝔽 ,返回 true .
j. 如果 nx 是 +∞ 𝔽 或
ny 是 -∞ 𝔽 ,返回 false .
k. 如果 ℝ (nx ) < ℝ (ny ),返回
true ;否则返回 false .
注 1
步骤 3 与算法中处理加法运算符 +
的步骤 1.c 不同 (13.15.3 ),使用逻辑与操作而不是逻辑或操作。
注 2
字符串的比较使用简单的按 UTF-16 代码单元值序列的字典顺序,没有尝试使用 Unicode 规范中定义的更复杂的、语义导向的字符或字符串相等性和排序顺序定义。因此,根据 Unicode
标准正规等价但不在相同规范化形式中的字符串值可能会被测试为不等。同样需要注意的是,对于包含 代理对 的字符串,按代码单元的字典顺序与按代码点的字典顺序不同。
7.2.14 IsLooselyEqual ( x , y )
抽象操作 IsLooselyEqual 接受参数 x (一个 ECMAScript 语言
值 )和 y (一个 ECMAScript 语言
值 ),并返回一个 正常
完成包含 布尔值或一个 抛出
完成 。它提供了 ==
操作符的语义。它在被调用时执行以下步骤:
1. 如果 类型 (x )
和 类型 (y )
相同,则
a. 返回 严格相等 (x ,
y )。
2. 如果 x 是 null 且 y 是
undefined ,返回 true 。
3. 如果 x 是 undefined 且 y
是
null ,返回 true 。
4.
注意:这一步在章节 B.3.6.2 中被替换。
5. 如果 x 是数字 且
y 是字符串 ,返回
! 宽松相等 (x ,
! 转换为数字 (y ))。
6. 如果 x 是字符串 且
y 是数字 ,返回
! 宽松相等 (! 转换为数字 (x ),
y )。
7. 如果 x 是 BigInt 且
y 是字符串 ,则
a. 令 n 为 字符串转换为
BigInt (y )。
b. 如果 n 是 undefined ,返回
false 。
c. 返回 ! 宽松相等 (x ,
n )。
8. 如果 x 是字符串 且
y 是
BigInt ,返回 ! 宽松相等 (y ,
x )。
9. 如果 x 是布尔值 ,返回
! 宽松相等 (! 转换为数字 (x ),
y )。
10. 如果 y 是布尔值 ,返回
! 宽松相等 (x ,
! 转换为数字 (y ))。
11. 如果 x 是字符串、数字、BigInt 或 Symbol 且 y 是对象 ,返回
! 宽松相等 (x ,
? 转换为原始值 (y ))。
12. 如果 x 是对象 且
y 是字符串、数字、BigInt 或 Symbol,返回 ! 宽松相等 (? 转换为原始值 (x ), y )。
13. 如果 x 是 BigInt 且
y 是数字 ,或如果
x 是数字 且
y 是 BigInt ,则
a. 如果 x 不是 有限 或
y 不是 有限 ,返回
false 。
b. 如果 ℝ (x ) = ℝ (y ),
返回
true ;否则返回 false 。
14. 返回 false 。
7.2.15 IsStrictlyEqual ( x , y )
抽象操作 IsStrictlyEqual 接受参数 x (一个 ECMAScript 语言值 )和
y (一个 ECMAScript
语言值 )并返回一个布尔值。它提供了 ===
操作符的语义。调用时执行以下步骤:
1. 如果 Type (x )
不是 Type (y ),返回
false 。
2. 如果 x 是一个数字 ,则
a. 返回 Number::equal (x ,
y )。
3. 返回 SameValueNonNumber (x ,
y )。
注
该算法在处理有符号零和 NaN 时与 SameValue 算法不同。
7.3 对象操作
7.3.1 MakeBasicObject ( internalSlotsList )
抽象操作 MakeBasicObject 接受参数 internalSlotsList (一个List ,包含内部插槽名称),并返回一个对象。它是所有以算法方式创建的
ECMAScript 对象的源头,包括普通对象和异态对象。它因此提取出了创建所有对象时使用的公共步骤,并集中了对象的创建过程。在调用时执行以下步骤:
1. 让 obj 成为一个新创建的对象,其内部包含 internalSlotsList
中每个名称的内部插槽。
2. 将 obj 的关键内部方法设置为默认的普通对象 定义,详见10.1 。
3. Assert :如果调用者不会覆盖 obj 的 [[GetPrototypeOf]] 和 [[SetPrototypeOf]] 关键内部方法中的任意一个,则
internalSlotsList 包含 [[Prototype]] 。
4. Assert :如果调用者不会覆盖 obj 的 [[SetPrototypeOf]] 、[[IsExtensible]] 和 [[PreventExtensions]] 关键内部方法中的所有一个或多个,则 internalSlotsList 包含 [[Extensible]] 。
5. 如果 internalSlotsList 包含 [[Extensible]] ,则将 obj .[[Extensible]] 设置为
true 。
6. 返回 obj 。
注
在本规范中,异态对象 通过首先调用 MakeBasicObject
来获取基本的基础对象,然后覆盖该对象的一些或全部内部方法,例如ArrayCreate 和BoundFunctionCreate 等抽象操作中创建。为了封装异态对象 的创建过程,对象的关键内部方法在这些操作外部永不修改。
7.3.2 Get ( O , P )
抽象操作 Get 接受参数 O (一个对象)和 P (一个属性键 ),并返回一个正常完成记录,其中包含 ECMAScript 语言值 或抛出完成记录 。用于检索对象的特定属性的值。调用时执行以下步骤:
1. 返回 ? O .[[Get]] (P , O ).
7.3.3 GetV ( V , P )
抽象操作 GetV 接受参数 V (一个ECMAScript 语言值 )和
P (一个属性键 ),并返回一个正常完成记录,其中包含 ECMAScript 语言值 或抛出完成记录 。用于检索ECMAScript
语言值 的特定属性的值。如果该值不是对象,则使用适合该值类型的包装对象进行属性查找。调用时执行以下步骤:
1. 让 O 成为 ? ToObject (V ).
2. 返回 ? O .[[Get]] (P , V ).
7.3.4 Set ( O , P , V , Throw )
抽象操作 Set 接受参数 O (一个对象)、P (一个属性键 )、V (一个ECMAScript 语言值 )和
Throw (一个布尔值),并返回一个正常完成记录,其中包含 抛出完成记录 。V 是要设置的属性的新值。调用时执行以下步骤:
1. 让 success 成为 ? O .[[Set]] (P , V ,
O ).
2. 如果 success 是 false 并且
Throw 是 true ,则抛出一个 TypeError 异常。
3. 返回 unused .
7.3.5 CreateDataProperty ( O , P , V )
抽象操作 CreateDataProperty 接受参数 O (一个对象)、P (一个属性键 )和
V (一个ECMAScript
语言值 ),并返回一个正常完成记录,其中包含 抛出完成记录 。用于创建对象的新自有属性。调用时执行以下步骤:
1. 让 newDesc 成为属性描述符 { [[Value]] :
V , [[Writable]] :
true , [[Enumerable]] : true , [[Configurable]] : true }.
2. 返回 ? O .[[DefineOwnProperty]] (P , newDesc ).
注
此抽象操作创建一个属性,其属性设置为 ECMAScript 语言赋值运算符创建的默认值。通常,该属性不会已存在。如果存在且不可配置,或者 O 不可扩展,则 [[DefineOwnProperty]] 将返回 false 。
7.3.6 CreateDataPropertyOrThrow ( O , P , V )
抽象操作 CreateDataPropertyOrThrow 接受参数 O (一个对象)、P (一个属性键 )和
V (一个ECMAScript
语言值 ),并返回一个正常完成记录,其中包含 抛出完成记录
unused 。用于创建对象的新自有属性。如果无法执行请求的属性更新,则抛出 TypeError 异常。调用时执行以下步骤:
1. 让 success 成为 ? CreateDataProperty (O , P , V ).
2. 如果 success 是 false ,则抛出一个
TypeError 异常。
3. 返回 unused .
注
此抽象操作创建一个属性,其属性设置为 ECMAScript 语言赋值运算符创建的默认值。通常,该属性不会已存在。如果存在且不可配置,或者 O 不可扩展,则 [[DefineOwnProperty]] 将返回 false ,导致此操作抛出
TypeError 异常。
7.3.7 CreateNonEnumerableDataPropertyOrThrow ( O , P ,
V )
抽象操作 CreateNonEnumerableDataPropertyOrThrow 接受参数 O (一个对象)、P (一个属性键 )和 V (一个ECMAScript 语言值 ),并返回
unused 。用于创建普通对象的新非可枚举自有属性。调用时执行以下步骤:
1. Assert : O
是一个普通的、可扩展的对象,并且没有不可配置的属性。
2. 让 newDesc 成为属性描述符 { [[Value]] :
V , [[Writable]] :
true , [[Enumerable]] : false , [[Configurable]] : true }.
3. 执行 ! DefinePropertyOrThrow (O ,
P , newDesc ).
4. 返回 unused .
注
此抽象操作创建一个属性,其属性设置为与 ECMAScript 语言赋值运算符创建的默认值相同,但不可枚举。通常情况下,该属性不存在。如果存在,则 DefinePropertyOrThrow
保证正常完成。
7.3.8 DefinePropertyOrThrow ( O , P , desc )
抽象操作 DefinePropertyOrThrow 接受参数 O (一个对象)、P (一个属性键 )和
desc (一个属性描述符 )并返回
normal completion
containing unused 或一个 throw
completion 。用于以可能引发 TypeError 异常的方式调用对象的 [[DefineOwnProperty]] 内部方法,如果无法执行所请求的属性更新。调用时执行以下步骤:
1. 让 success 成为 ? O .[[DefineOwnProperty]] (P ,
desc ).
2. 如果 success 是 false ,则抛出
TypeError 异常。
3. 返回 unused .
7.3.9 DeletePropertyOrThrow ( O , P )
抽象操作 DeletePropertyOrThrow 接受参数 O (一个对象)和 P (一个属性键 )并返回 normal completion
containing unused 或一个 throw
completion 。用于移除对象的特定自有属性。如果属性不可配置,则抛出异常。调用时执行以下步骤:
1. 让 success 成为 ? O .[[Delete]] (P ).
2. 如果 success 是 false ,则抛出
TypeError 异常。
3. 返回 unused .
7.3.10 GetMethod ( V , P )
抽象操作 GetMethod 接受参数 V (一个ECMAScript 语言值 )
和 P (一个属性键 )并返回一个normal completion
containing 包含函数对象 或undefined ,或一个throw
completion 。用于在期望属性值为函数时获取ECMAScript
语言值 的特定属性值。调用时执行以下步骤:
1. 让 func 成为 ? GetV (V ,
P ).
2. 如果 func 是 undefined 或
null ,则返回 undefined 。
3. 如果 IsCallable (func ) 是
false ,则抛出 TypeError 异常。
4. 返回 func 。
7.3.11 HasProperty ( O , P )
抽象操作 HasProperty 接受参数 O (一个 Object)和 P (一个 属性键 )并返回一个 normal completion
containing
一个 Boolean 或一个 throw
completion 。它用于确定对象是否具有指定的 属性键 ,该属性可以是自有的或继承的。调用时执行以下步骤:
1. 返回 ? O .[[HasProperty]] (P )。
7.3.12 HasOwnProperty ( O , P )
抽象操作 HasOwnProperty 接受参数 O (一个 Object)和 P (一个 属性键 )并返回一个 normal completion
containing
一个 Boolean 或一个 throw
completion 。它用于确定对象是否具有指定的自有 属性键 。调用时执行以下步骤:
1. Let desc be ? O .[[GetOwnProperty]] (P ).
2. If desc is undefined , return
false .
3. Return true .
7.3.13 Call ( F , V [ , argumentsList ] )
抽象操作 Call 接受参数 F (一个 ECMAScript 语言值 )和
V (一个
ECMAScript 语言值 )以及可选参数
argumentsList (一个 List ,包含
ECMAScript 语言值 )并返回一个
normal completion
containing
一个 ECMAScript 语言值 或一个
throw
completion 。它用于调用
函数对象 的 [[Call]]
内部方法。
F 是 函数对象 ,V 是 [[Call]] 的
this 值,argumentsList 是传递给内部方法的对应参数。如果 argumentsList 不存在,则使用一个新的空
List
作为其值。调用时执行以下步骤:
1.
如果argumentsList 不存在,则将argumentsList 设为一个新的空List 。
2. 如果IsCallable (F )的返回值为false ,则抛出TypeError 异常。
3. 返回 ? F .[[Call]] (V , argumentsList )。
7.3.14 构造(F [ , argumentsList [ , newTarget ]
])
抽象操作构造(Construct)接受参数F (一个构造函数 )和可选参数argumentsList (一个List ,包含ECMAScript语言值 )以及newTarget (一个构造函数 ),并返回一个包含对象的正常完成 或抛出异常的抛出完成 。它用于调用函数对象 的[[Construct]] 内部方法。参数argumentsList 和newTarget 将作为相应内部方法的参数传递。如果argumentsList 不存在,则使用一个新的空List 作为其值。如果newTarget 不存在,则使用F 作为其值。调用时执行以下步骤:
1. 如果newTarget 不存在,则将newTarget 设为F 。
2.
如果argumentsList 不存在,则将argumentsList 设为一个新的空List 。
3. 返回 ? F .[[Construct]] (argumentsList , newTarget )。
注
如果newTarget 不存在,则该操作等效于:new F(...argumentsList)
7.3.15 SetIntegrityLevel ( O , level )
抽象操作 SetIntegrityLevel 接受参数 O (一个对象)和 level (sealed 或
frozen ),并返回一个包含布尔值的 正常完成 或抛出异常的
抛出完成 。它用于固定对象的自有属性集合。调用时执行以下步骤:
1. 设 status 为 ? O .[[PreventExtensions]] ()。
2. 如果 status 是 false ,则返回
false 。
3. 设 keys 为 ? O .[[OwnPropertyKeys]] ()。
4. 如果 level 是 sealed ,则
a. 对于 keys 的每个元素 k ,执行
i. 执行 ? DefinePropertyOrThrow (O , k ,
PropertyDescriptor { [[Configurable]] : false
})。
5. 否则,
a. Assert : level 是
frozen 。
b. 对于 keys 的每个元素 k ,执行
i. 设 currentDesc 为 ? O .[[GetOwnProperty]] (k )。
ii. 如果 currentDesc 不是
undefined ,则
1. 如果 IsAccessorDescriptor (currentDesc )
是 true ,则
a. 设 desc 为 PropertyDescriptor { [[Configurable]] : false }。
2. 否则,
a. 设 desc 为 PropertyDescriptor { [[Configurable]] : false , [[Writable]] : false }。
3. 执行 ? DefinePropertyOrThrow (O , k ,
desc )。
6. 返回 true 。
7.3.16 TestIntegrityLevel ( O , level )
抽象操作 TestIntegrityLevel 接受参数 O (一个对象)和 level (sealed 或
frozen ),并返回一个包含布尔值的 正常完成 或抛出异常的
抛出完成 。它用于确定对象的自有属性集合是否被固定。调用时执行以下步骤:
1. 设 extensible 为 ? IsExtensible (O )。
2. 如果 extensible 是 true ,则返回
false 。
3. 注意:如果对象是可扩展的,则不检查其任何属性。
4. 设 keys 为 ? O .[[OwnPropertyKeys]] ()。
5. 对于 keys 的每个元素 k ,执行
a. 设 currentDesc 为 ? O .[[GetOwnProperty]] (k )。
b. 如果 currentDesc 不是 undefined ,则
i. 如果 currentDesc .[[Configurable]] 是 true ,则返回 false 。
ii. 如果 level 是 frozen 并且
IsDataDescriptor (currentDesc )
是 true ,则
1. 如果 currentDesc .[[Writable]] 是 true ,则返回 false 。
6. 返回 true 。
7.3.17 CreateArrayFromList ( elements )
抽象操作 CreateArrayFromList 接受参数 elements (一个 List ,包含 ECMAScript
语言值 )并返回一个数组。它用于创建一个数组,其元素由 elements 提供。调用时执行以下步骤:
1. 设 array 为 ! ArrayCreate (0)。
2. 设 n 为 0。
3. 对于 elements 的每个元素 e ,执行
a. 执行 ! CreateDataPropertyOrThrow (array ,
! ToString (𝔽 (n )),
e )。
b. 将 n 设为 n + 1。
4. 返回 array 。
7.3.18 LengthOfArrayLike ( obj )
抽象操作 LengthOfArrayLike 接受参数 obj (一个对象)并返回一个正常完成,包含 非负整数整数 或一个抛出完成 。它返回类似数组对象的"length" 属性值。调用时执行以下步骤:
1. 返回 ℝ (? ToLength (? Get (obj ,
"length" )))。
类似数组对象 是指该操作返回正常完成 的任何对象。
注 1
通常,类似数组对象还会具有一些以
整数索引 命名的属性。但这不是此定义的要求。
注 2
数组和字符串对象是类似数组对象的示例。
7.3.19 CreateListFromArrayLike ( obj [ , elementTypes ]
)
抽象操作 CreateListFromArrayLike 接受参数 obj (一个ECMAScript
语言值 )和可选参数 elementTypes (一个List ,包含
ECMAScript 语言类型的名称),返回正常完成,包含 一个List 值,其元素由obj 的索引属性提供。
elementTypes 包含创建的List 的元素值允许的
ECMAScript 语言类型名称。调用时执行以下步骤:
1. 如果 elementTypes 不存在,则将 elementTypes 设置为«
Undefined, Null, Boolean, String, Symbol, Number, BigInt, Object »。
2. 如果 obj 不是对象 ,则抛出
TypeError 异常。
3. 让 len 是 ? LengthOfArrayLike (obj )。
4. 让 list 是一个新的空List 。
5. 让 index 是 0。
6. 重复,当 index < len 时,
a. 让 indexName 是 ! ToString (𝔽 (index ))。
b. 让 next 是 ? Get (obj , indexName )。
c. 如果 elementTypes 不包含 Type (next ),则抛出
TypeError 异常。
d. 将 next 追加到 list 。
e. 将 index 设置为 index + 1。
7. 返回 list 。
7.3.20 Invoke ( V , P [ , argumentsList ] )
抽象操作 Invoke 接受参数 V (一个ECMAScript 语言值 )和
P (一个属性键 ),可选参数
argumentsList (一个List ,包含ECMAScript
语言值 ),返回正常完成,包含 一个ECMAScript 语言值 或者抛出完成 。该操作用于调用ECMAScript 语言值 的方法属性。
V 既用作属性查找点也用作调用的this 值。 argumentsList 是传递给方法的参数值列表。如果
argumentsList 不存在,则使用一个新的空List 作为其值。调用时执行以下步骤:
1. 如果 argumentsList 不存在,则将 argumentsList
设置为一个新的空List 。
2. 让 func 是 ? GetV (V ,
P )。
3. 返回 ? Call (func ,
V , argumentsList )。
7.3.21 OrdinaryHasInstance ( C , O )
抽象操作 OrdinaryHasInstance 接受参数 C (一个ECMAScript
语言值 )和 O (一个ECMAScript
语言值 ),返回正常完成,包含 一个布尔值或者抛出完成 。它实现了确定O 是否从C 提供的实例对象继承路径的默认算法。调用时执行以下步骤:
1. 如果 IsCallable (C ) 为
false ,返回 false 。
2. 如果 C 有一个 [[BoundTargetFunction]] 内部插槽,则
a. 让 BC 为 C .[[BoundTargetFunction]] 。
b. 返回 ? InstanceofOperator (O , BC )。
3. 如果 O 不是一个对象 ,返回 false 。
4. 让 P 为 ? Get (C ,
"prototype" )。
5. 如果 P 不是一个对象 ,抛出一个
TypeError 异常。
6. 重复,
a. 将 O 设置为 ? O .[[GetPrototypeOf]] ()。
b. 如果 O 是 null ,返回
false 。
c. 如果 SameValue (P ,
O ) 是 true ,返回 true 。
7.3.22 SpeciesConstructor ( O , defaultConstructor )
抽象操作 SpeciesConstructor 接受参数 O (一个对象)和 defaultConstructor (一个构造函数 ),返回正常完成,包含 一个构造函数 或者一个抛出完成 。它用于获取应该用于创建从
O 派生的新对象的构造函数 。如果无法从 O 开始找到一个构造函数 的@@species 属性,则使用
defaultConstructor 。调用时执行以下步骤:
1. 让 C 为 ? Get (O ,
"constructor" )。
2. 如果 C 是 undefined ,返回
defaultConstructor 。
3. 如果 C 不是一个对象 ,抛出一个
TypeError 异常。
4. 让 S 为 ? Get (C ,
@@species )。
5. 如果 S 是 undefined 或者
null ,返回 defaultConstructor 。
6. 如果 IsConstructor (S ) 是
true ,返回 S 。
7. 抛出一个 TypeError 异常。
7.3.23 EnumerableOwnProperties ( O , kind )
抽象操作 EnumerableOwnProperties 接受参数 O (一个对象)和 kind
(key 、value 或 key+value ),返回
一个正常完成,包含
一个列表 的ECMAScript
语言值 或者一个抛出完成 。调用时执行以下步骤:
1. 让 ownKeys 为 ? O .[[OwnPropertyKeys]] ()。
2. 让 results 为一个新的空列表 。
3. 对于 ownKeys 的每个元素 key ,做如下操作:
a. 如果 key 是字符串 ,那么:
i. 让 desc 为 ? O .[[GetOwnProperty]] (key )。
ii. 如果 desc 不是 undefined 并且
desc .[[Enumerable]] 是 true ,那么:
1. 如果 kind 是 key ,那么
a. 将 key 添加到 results 中。
2. 否则,
a. 让 value 为 ? Get (O , key )。
b. 如果 kind 是
value ,那么:
i. 将 value 添加到 results
中。
c. 否则,
i. 断言 :kind 是
key+value 。
ii. 让 entry 为 CreateArrayFromList («
key , value »)。
iii. 将 entry 添加到 results
中。
4. 返回 results 。
7.3.24 GetFunctionRealm ( obj )
抽象操作 GetFunctionRealm 接受参数 obj (一个函数对象 ),返回一个正常完成,包含 一个域记录 或者一个抛出完成 。调用时执行以下步骤:
1. 如果 obj 拥有一个 [[Realm]] 内部插槽,则:
a. 返回 obj .[[Realm]] 。
2. 如果 obj 是一个绑定函数的异域对象 ,则:
a. 让 boundTargetFunction 为 obj .[[BoundTargetFunction]] 。
b. 返回 ? GetFunctionRealm (boundTargetFunction )。
3. 如果 obj 是一个代理的异域对象 ,则:
a. 执行 ? ValidateNonRevokedProxy (obj )。
b. 让 proxyTarget 为 obj .[[ProxyTarget]] 。
c. 返回 ? GetFunctionRealm (proxyTarget )。
4. 返回 当前域记录 。
注
如果 obj 是一个非标准函数异域对象 且没有 [[Realm]] 内部插槽,则步骤 4 会被执行。
7.3.25 CopyDataProperties ( target , source ,
excludedItems )
抽象操作 CopyDataProperties 接受参数 target (一个对象),source
(一个ECMAScript 语言值 )和
excludedItems (一个列表 ,包含属性键),并返回一个正常完成,包含
unused 或者一个抛出完成 。调用时执行以下步骤:
1. 如果 source 是 undefined 或
null ,则返回 unused 。
2. 让 from 为 ! ToObject (source )。
3. 让 keys 为 ? from .[[OwnPropertyKeys]] ()。
4. 对于 keys 中的每个元素 nextKey ,执行以下步骤:
a. 让 excluded 为 false 。
b. 对于 excludedItems 中的每个元素 e ,执行以下步骤:
i. 如果 SameValue (e ,
nextKey ) 是 true ,则执行以下步骤:
1. 将 excluded 设为 true 。
c. 如果 excluded 是 false ,则执行以下步骤:
i. 让 desc 为 ? from .[[GetOwnProperty]] (nextKey )。
ii. 如果 desc 不是 undefined 并且
desc .[[Enumerable]] 是 true ,则执行以下步骤:
1. 让 propValue 为 ? Get (from , nextKey )。
2. 执行 ! CreateDataPropertyOrThrow (target ,
nextKey , propValue )。
5. 返回 unused 。
注
这里传入的目标对象始终是一个新创建的对象,在发生错误抛出时不会直接访问到它。
7.3.26 PrivateElementFind ( O , P )
抽象操作 PrivateElementFind 接受参数 O (一个对象)和 P (一个私有名称 ),并返回一个PrivateElement 或者empty 。调用时执行以下步骤:
1. 如果 O .[[PrivateElements]]
包含一个PrivateElement
pe ,
使得 pe .[[Key]] 是 P ,则执行以下步骤:
a. 返回 pe 。
2. 返回 empty 。
7.3.27 PrivateFieldAdd ( O , P , value )
抽象操作 PrivateFieldAdd 接受参数 O (一个对象),P (一个私有名称 ),和
value (一个ECMAScript
语言值 ),并返回一个normal completion
containing unused 或者一个throw
completion 。调用时执行以下步骤:
1. If the host is a web browser, then
a. 执行 ? HostEnsureCanAddPrivateElement (O ).
2. Let entry be PrivateElementFind (O ,
P ).
3. If entry is not empty , throw a
TypeError exception.
4. Append PrivateElement
{ [[Key]] : P , [[Kind]] :
field , [[Value]] : value } to
O .[[PrivateElements]] .
5. Return unused .
7.3.28 PrivateMethodOrAccessorAdd ( O , method )
抽象操作 PrivateMethodOrAccessorAdd 接受参数 O (一个对象)和 method (一个 PrivateElement ),并返回一个包含正常完成的
未使用
或抛出完成。调用时执行以下步骤:
1. Assert : method .[[Kind]] 是 method 或 accessor 。
2. 如果 宿主环境 是 Web 浏览器,则执行:
a. 执行 ? HostEnsureCanAddPrivateElement (O )。
3. 让 entry 成为 PrivateElementFind (O ,
method .[[Key]] )。
4. 如果 entry 不是 empty ,则抛出一个
TypeError 异常。
5. 将 method 添加到 O .[[PrivateElements]] 。
6. 返回 unused 。
注
私有方法和访问器的值在实例之间是共享的。此操作不会创建方法或访问器的新副本。
7.3.29 HostEnsureCanAddPrivateElement ( O )
宿主定义的抽象操作 HostEnsureCanAddPrivateElement 接受参数 O (一个对象),并返回一个包含正常完成的 未使用
或抛出完成。它允许宿主环境阻止将私有元素添加到特定的宿主定义的异域对象。
HostEnsureCanAddPrivateElement 的实现必须符合以下要求:
HostEnsureCanAddPrivateElement 的默认实现是返回 NormalCompletion (unused )。
此抽象操作仅由 ECMAScript 宿主 ,即 Web 浏览器调用。
7.3.30 PrivateGet ( O , P )
抽象操作 PrivateGet 接受参数 O (一个对象)和 P (一个私有名称),并返回一个包含 ECMAScript 语言值的普通完成或抛出完成。调用时执行以下步骤:
1. 令 entry 为 PrivateElementFind (O ,
P )。
2. 如果 entry 为空,则抛出 TypeError 异常。
3. 如果 entry .[[Kind]] 是
field 或 method ,则
a. 返回 entry .[[Value]] 。
4. Assert :确保 entry .[[Kind]] 是 accessor 。
5. 如果 entry .[[Get]] 是
undefined ,则抛出 TypeError 异常。
6. 令 getter 为 entry .[[Get]] 。
7. 返回 ? Call (getter ,
O )。
7.3.31 PrivateSet ( O , P , value )
抽象操作 PrivateSet 接受参数 O (一个对象)、P (一个私有名称)和 value (一个 ECMAScript
语言值),并返回一个包含未使用的普通完成或抛出完成。调用时执行以下步骤:
1. 令 entry 为 PrivateElementFind (O ,
P )。
2. 如果 entry 为空,则抛出 TypeError 异常。
3. 如果 entry .[[Kind]] 是
field ,则
a. 将 entry .[[Value]] 设置为
value 。
4. 否则,如果 entry .[[Kind]] 是
method ,则
a. 抛出 TypeError 异常。
5. 否则,
a. Assert : 确保 entry .[[Kind]] 是 accessor 。
b. 如果 entry .[[Set]] 是
undefined ,则抛出 TypeError 异常。
c. 令 setter 为 entry .[[Set]] 。
d. 执行 ? Call (setter , O , «
value »)。
6. 返回 unused 。
7.3.32 DefineField ( receiver , fieldRecord )
抽象操作 DefineField 接受参数 receiver (一个对象)和 fieldRecord (一个 ClassFieldDefinition
Record ),并返回一个包含未使用的普通完成或抛出完成。调用时执行以下步骤:
1. 令 fieldName 为 fieldRecord .[[Name]] 。
2. 令 initializer 为 fieldRecord .[[Initializer]] 。
3. 如果 initializer 不为空,则
a. 令 initValue 为 ? Call (initializer , receiver )。
4. 否则,
a. 令 initValue 为 undefined 。
5. 如果 fieldName 是一个 Private Name ,则
a. 执行 ? PrivateFieldAdd (receiver ,
fieldName , initValue )。
6. 否则,
a. Assert : 确保 IsPropertyKey (fieldName )
是 true 。
b. 执行 ? CreateDataPropertyOrThrow (receiver ,
fieldName , initValue )。
7. 返回 unused 。
7.3.33 InitializeInstanceElements ( O , constructor )
抽象操作 InitializeInstanceElements 接受参数 O (一个对象)和 constructor (一个 ECMAScript function
object ),并返回一个包含未使用的普通完成或抛出完成。调用时执行以下步骤:
1. 令 methods 为 constructor .[[PrivateMethods]] 的值。
2. 对于每个 PrivateElement
method 在 methods 中,执行
a. 执行 ? PrivateMethodOrAccessorAdd (O ,
method )。
3. 令 fields 为 constructor .[[Fields]] 的值。
4. 对于每个元素 fieldRecord 在 fields 中,执行
a. 执行 ? DefineField (O , fieldRecord )。
5. 返回 unused 。
7.3.34 AddValueToKeyedGroup ( groups , key ,
value )
抽象操作 AddValueToKeyedGroup 接受参数 groups (一个包含字段 [[Key]] (一个 ECMAScript
语言值)和 [[Elements]] (一个 ECMAScript 语言值列表)的 List
的记录),key (一个 ECMAScript 语言值)和 value (一个 ECMAScript 语言值),并返回
unused 。调用时执行以下步骤:
1. 对于每个 记录 { [[Key]] , [[Elements]] } g 在 groups
中,执行
a. 如果 SameValue (g .[[Key]] , key ) 的结果为 true ,则
i. Assert : 正好有一个 groups
的元素符合此条件。
ii. 将 value 追加到 g .[[Elements]] 中。
iii. 返回 unused 。
2. 令 group 为记录 { [[Key]] :
key , [[Elements]] : « value » }。
3. 将 group 追加到 groups 中。
4. 返回 unused 。
7.3.35 GroupBy ( items , callbackfn ,
keyCoercion )
抽象操作 GroupBy 接受参数 items (一个 ECMAScript 语言值)、callbackfn (一个 ECMAScript 语言值)和
keyCoercion (property 或 zero ),并返回一个包含字段 [[Key]] (一个 ECMAScript 语言值)和 [[Elements]] (一个 ECMAScript
语言值列表)的 List 的记录或一个
throw
completion 。调用时执行以下步骤:
1. 执行 ? RequireObjectCoercible (items ).
2. 如果 IsCallable (callbackfn )
的结果为 false ,则抛出一个 TypeError 异常。
3. 令 groups 为一个新的空 List 。
4. 令 iteratorRecord 为 ? GetIterator (items , sync ).
5. 令 k 为 0。
6. 重复执行
a. 如果 k ≥ 253 - 1,则
i. 令 error 为 ThrowCompletion (一个新创建的
TypeError 对象)。
ii. 返回 ? IteratorClose (iteratorRecord ,
error ).
b. 令 next 为 ? IteratorStepValue (iteratorRecord ).
c. 如果 next 为 done ,则
i. 返回 groups 。
d. 令 value 为 next 。
e. 令 key 为 Completion (Call (callbackfn , undefined , «
value , 𝔽 (k ) »)).
f. IfAbruptCloseIterator (key ,
iteratorRecord ).
g. 如果 keyCoercion 为 property ,则
i. 将 key 设置为 Completion (ToPropertyKey (key )).
ii. IfAbruptCloseIterator (key ,
iteratorRecord ).
h. 否则,
i. Assert : keyCoercion 为
zero 。
ii. 如果 key 是 -0 𝔽 ,则将
key 设置为 +0 𝔽 。
i. 执行 AddValueToKeyedGroup (groups ,
key , value ).
j. 将 k 设置为 k + 1。
7.4 迭代器对象操作
请参阅通用迭代接口(27.1 )。
7.4.1 迭代器记录
迭代器记录 是用于封装迭代器或异步迭代器及其 next
方法的 记录 值。
迭代器记录具有以下在 表格 15 中列出的字段。
表格 15: 迭代器记录 字段
字段名
值
含义
[[Iterator]]
一个对象
符合 Iterator 或 AsyncIterator 接口的对象。
[[NextMethod]]
一个 ECMAScript 语言值
[[Iterator]] 对象的 next
方法。
[[Done]]
一个布尔值
表示迭代器是否已关闭。
7.4.2 GetIteratorFromMethod ( obj , method )
抽象操作 GetIteratorFromMethod 接受参数 obj (一个 ECMAScript
语言值 )
和 method (一个 函数对象 ),并返回一个包含正常完成或抛出完成的 迭代器记录 。
当调用时,执行以下步骤:
1. 令 iterator be ? Call (method ,
obj ).
2. If iterator 不是一个对象 ,抛出一个
TypeError 异常。
3. 令 nextMethod be ? Get (iterator ,
"next" ).
4. 令 iteratorRecord 为 迭代器记录 { [[Iterator]] : iterator , [[NextMethod]] :
nextMethod ,
[[Done]] : false }。
5. 返回 iteratorRecord 。
7.4.3 GetIterator ( obj , kind )
抽象操作 GetIterator 接受参数 obj (一个 ECMAScript 语言值)和 kind (sync 或
async ),并返回一个包含正常完成状态的迭代器记录或抛出异常完成状态。调用时执行以下步骤:
1. 如果 kind 是 async ,则
a. 令 method 为 ? GetMethod (obj , @@asyncIterator )。
b. 如果 method 是 undefined ,则
i. 令 syncMethod 为 ? GetMethod (obj , @@iterator )。
ii. 如果 syncMethod 是
undefined ,则抛出 TypeError 异常。
iii. 令 syncIteratorRecord 为 ? GetIteratorFromMethod (obj ,
syncMethod )。
iv. 返回 CreateAsyncFromSyncIterator (syncIteratorRecord )。
2. 否则,
a. 令 method 为 ? GetMethod (obj , @@iterator )。
3. 如果 method 是 undefined ,则抛出
TypeError 异常。
4. 返回 ? GetIteratorFromMethod (obj , method )。
7.4.4 IteratorNext ( iteratorRecord [ , value ] )
抽象操作 IteratorNext 接受参数 iteratorRecord (一个 Iterator
Record )和可选参数 value (一个 ECMAScript
语言值 ),并返回一个包含正常完成状态的对象或抛出异常完成状态。调用时执行以下步骤:
1. 如果 value 不存在,则
a. 令 result 为 ? Call (iteratorRecord .[[NextMethod]] , iteratorRecord .[[Iterator]] )。
2. 否则,
a. 令 result 为 ? Call (iteratorRecord .[[NextMethod]] , iteratorRecord .[[Iterator]] , « value »)。
3. 如果 result 不是对象 ,则抛出
TypeError 异常。
4. 返回 result 。
7.4.5 IteratorComplete ( iterResult )
抽象操作 IteratorComplete 接受参数 iterResult (一个对象)并返回一个包含正常完成状态的布尔值或抛出异常完成状态。调用时执行以下步骤:
1. 返回 ToBoolean (? Get (iterResult , "done" ))。
7.4.6 IteratorValue ( iterResult )
抽象操作 IteratorValue 接受参数 iterResult (一个对象)并返回一个包含正常完成状态的 ECMAScript 语言值或抛出异常完成状态。调用时执行以下步骤:
1. 返回 ? Get (iterResult , "value" )。
7.4.7 IteratorStep ( iteratorRecord )
抽象操作 IteratorStep 接受参数 iteratorRecord (一个 迭代器记录 ),并返回一个正常完成包含对象或
false ,或者抛出完成。它通过调用 iteratorRecord .[[NextMethod]] 从
iteratorRecord .[[Iterator]] 请求下一个值,并根据情况返回 false
表示迭代器已经结束,或者返回可用的 IteratorResult 对象。调用时执行以下步骤:
1. 令 result 为 ? IteratorNext (iteratorRecord ).
2. 令 done 为 ? IteratorComplete (result ).
3. 如果 done 为 true ,则返回
false 。
4. 返回 result 。
7.4.8 IteratorStepValue ( iteratorRecord )
抽象操作 IteratorStepValue 接受参数 iteratorRecord (一个 迭代器记录 ),并返回一个正常完成包含
ECMAScript 语言值或 done ,或者抛出完成。它通过调用 iteratorRecord .[[NextMethod]] 从 iteratorRecord .[[Iterator]]
请求下一个值,并根据情况返回 done 表示迭代器已经结束,或者返回从 IteratorResult 对象中获取的值。调用时执行以下步骤:
1. 令 result 为 Completion (IteratorNext (iteratorRecord )).
2. If result is a throw
completion , 则
a. 将 iteratorRecord .[[Done]]
设置为 true 。
b. 返回 ? result 。
3. 将 result 设置为 ! result 。
4. 令 done 为 Completion (IteratorComplete (result )).
5. If done 是一个 throw
completion , 则
a. 将 iteratorRecord .[[Done]]
设置为 true 。
b. 返回 ? done 。
6. 将 done 设置为 ! done 。
7. If done 是 true , 则
a. 将 iteratorRecord .[[Done]]
设置为 true 。
b. 返回 done 。
8. 令 value 为 Completion (Get (result , "value" )).
9. If value 是一个 throw
completion , 则
a. 将 iteratorRecord .[[Done]]
设置为 true 。
10. 返回 ? value 。
7.4.9 IteratorClose ( iteratorRecord , completion )
抽象操作 IteratorClose 接受参数 iteratorRecord (一个 迭代器记录 )和
completion (一个 完成记录 ),并返回一个
完成记录 。它用于通知迭代器在达到完成状态时执行其通常执行的任何操作。调用时执行以下步骤:
1. Assert : iteratorRecord .[[Iterator]] 是一个对象 。
2. 令 iterator 为 iteratorRecord .[[Iterator]] 。
3. 令 innerResult 为 Completion (GetMethod (iterator , "return" )).
4. 如果 innerResult 是一个 正常完成 ,则
a. 令 return 为 innerResult .[[Value]] 。
b. 如果 return 是 undefined ,则返回
? completion 。
c. 将 innerResult 设置为 Completion (Call (return , iterator )).
5. 如果 completion 是一个 抛出完成 ,则返回
? completion 。
6. 如果 innerResult 是一个 抛出完成 ,则返回
? innerResult 。
7. 如果 innerResult .[[Value]]
不是一个对象 ,则抛出
TypeError 异常。
8. 返回 ? completion 。
7.4.10 IfAbruptCloseIterator ( value , iteratorRecord )
IfAbruptCloseIterator 是一个使用 迭代器记录 的一系列算法步骤的简写形式。形式为:
1. IfAbruptCloseIterator (value ,
iteratorRecord ).
意味着与以下内容相同:
1. Assert : value 是一个 完成记录 。
2. 如果 value 是一个 突然完成 ,则返回
? IteratorClose (iteratorRecord , value )。
3. 否则,将 value 设置为 ! value 。
7.4.11 AsyncIteratorClose ( iteratorRecord , completion )
异步抽象操作 AsyncIteratorClose 接受参数 iteratorRecord (一个 迭代器记录 )和
completion (一个
完成记录 ),并返回一个
完成记录 。
用于通知异步迭代器,在达到完成状态时执行其通常执行的任何操作。调用时执行以下步骤:
1. Assert : iteratorRecord .[[Iterator]] 是一个对象 。
2. 让 iterator 为 iteratorRecord .[[Iterator]] 。
3. 让 innerResult 为 Completion (GetMethod (iterator , "return" ))。
4. 如果 innerResult 是一个 正常完成 ,则:
a. 让 return 为 innerResult .[[Value]] 。
b. 如果 return 是 undefined ,返回
? completion 。
c. 将 innerResult 设为 Completion (Call (return , iterator ))。
d. 如果 innerResult 是一个 正常完成 ,
将 innerResult 设为 Completion (Await (innerResult .[[Value]] ))。
5. 如果 completion 是一个 抛出完成 ,返回
? completion 。
6. 如果 innerResult 是一个 抛出完成 ,返回
? innerResult 。
7. 如果 innerResult .[[Value]]
不是一个对象 ,
抛出 TypeError 异常。
8. 返回 ? completion 。
7.4.12 CreateIterResultObject ( value , done )
抽象操作 CreateIterResultObject 接受参数 value (一个 ECMAScript
语言值 )和 done (一个布尔值),并返回符合
IteratorResult 接口的对象。它在调用时执行以下步骤:
1. 让 obj 为 OrdinaryObjectCreate (%Object.prototype% )。
2. 执行 ! CreateDataPropertyOrThrow (obj ,
"value" , value )。
3. 执行 ! CreateDataPropertyOrThrow (obj ,
"done" , done )。
4. 返回 obj 。
7.4.13 CreateListIteratorRecord ( list )
抽象操作 CreateListIteratorRecord 接受参数 list (一个 List ,包含
ECMAScript 语言值 ),并返回一个
Iterator Record 。它创建一个迭代器对象记录,其
next
方法返回
list 的连续元素。在调用时执行以下步骤:
1. 让 closure 成为一个没有参数的新 Abstract Closure ,它捕获
list ,并在调用时执行以下步骤:
a. 对于 list 的每个元素 E ,执行
i. 执行 ? GeneratorYield (CreateIterResultObject (E ,
false ))。
b. 返回 NormalCompletion (undefined )。
2. 让 iterator 成为 CreateIteratorFromClosure (closure ,
empty , %IteratorPrototype% )。
3. 返回 Iterator
Record { [[Iterator]] : iterator , [[NextMethod]] :
%GeneratorFunction.prototype.prototype.next%, [[Done]] :
false }。
注
列表迭代器对象对 ECMAScript 代码不可直接访问。
7.4.14 IteratorToList ( iteratorRecord )
抽象操作 IteratorToList 接受参数 iteratorRecord (一个 Iterator
Record )并返回一个包含 正常完成 ,其包含
List ,或者一个
抛出完成 。在调用时执行以下步骤:
1. 让 values 成为一个新的空 List 。
2. 重复执行,
a. 让 next 成为 ? IteratorStepValue (iteratorRecord )。
b. 如果 next 是 done ,那么
i. 返回 values 。
c. 将 next 追加到 values 。
8 语法导向操作
除了本节中定义的操作外,专门的语法导向操作 在本规范的各个地方进行了定义。
8.1 运行时语义:评估
语法导向操作 Evaluation 不接受参数并返回一个完成记录 。
注
该操作的定义分布在本规范的“ECMAScript 语言”部分。每个定义都出现在相关产生式的定义后面。
8.2 Scope 分析
8.2.1 静态语义:BoundNames
语法导向操作 BoundNames 不接受参数,并返回一个字符串列表(List )。
注
"*default*" 在本规范中用作模块默认导出的合成名称,当没有其他名称时使用。模块的 [[Environment]] 中创建一个以该名称命名的条目,并保存相应的值。通过调用 ResolveExport(exportName [ ,
resolveSet ]) 解析名为 "default" 的导出,模块会返回一个 ResolvedBinding Record ,其 [[BindingName]] 为 "*default*" ,然后在模块的 [[Environment]] 中解析为上述值。这仅用于规范的便利性,使得匿名默认导出能够像其他任何导出一样解析。这个
"*default*" 字符串对 ECMAScript 代码或模块链接算法是不可访问的。
它在以下产生式上分段定义:
BindingIdentifier
: Identifier
1. 返回一个 List ,其唯一元素是
Identifier
的字符串值,来自于
Identifier 。
BindingIdentifier
: yield
1. 返回 « "yield" »。
BindingIdentifier
: await
1. 返回 « "await" »。
LexicalDeclaration
:
LetOrConst
BindingList
;
1. 返回 BoundNames 的结果,
来自于 BindingList 。
BindingList
:
BindingList
,
LexicalBinding
1. 令 names1 为 BoundNames 的结果,
来自于 BindingList 。
2. 令 names2 为 BoundNames 的结果,
来自于 LexicalBinding 。
3. 返回 list-concatenation 的结果,
包括 names1 和 names2 。
LexicalBinding
:
BindingIdentifier
Initializer opt
1. 返回 BoundNames 的结果,
来自于 BindingIdentifier 。
LexicalBinding
:
BindingPattern
Initializer
1. 返回 BoundNames 的结果,
来自于 BindingPattern 。
VariableDeclarationList
:
VariableDeclarationList
,
VariableDeclaration
1. 令 names1 为 BoundNames 的结果,
来自于 VariableDeclarationList 。
2. 令 names2 为 BoundNames 的结果,
来自于 VariableDeclaration 。
3. 返回 list-concatenation 的结果,
包括 names1 和 names2 。
VariableDeclaration
:
BindingIdentifier
Initializer opt
1. 返回 BoundNames 的结果,
来自于 BindingIdentifier 。
VariableDeclaration
:
BindingPattern
Initializer
1. 返回 BoundNames 的结果,
来自于 BindingPattern 。
ObjectBindingPattern
:
{
}
1. 返回一个新的空 List 。
ObjectBindingPattern
:
{
BindingPropertyList
,
BindingRestProperty
}
1. 让 names1 成为 BoundNames 的结果,
其中 BindingPropertyList 是指向的非终结符。
2. 让 names2 成为 BoundNames 的结果,
其中 BindingRestProperty 是指向的非终结符。
3. 返回 list-concatenation 的结果,
其中包含 names1 和 names2 。
ArrayBindingPattern
:
[
Elision opt
]
1. 返回一个新的空 List 。
ArrayBindingPattern
:
[
Elision opt
BindingRestElement
]
1. 让 names 成为 BoundNames 的结果,
其中 BindingRestElement 是指向的非终结符。
ArrayBindingPattern
:
[
BindingElementList
,
Elision opt
]
1. 让 names1 成为 BoundNames 的结果,
其中 BindingElementList 是指向的非终结符。
2. 让 names2 成为 BoundNames 的结果,
其中 BindingRestElement 是指向的非终结符。
3. 返回 list-concatenation 的结果,
其中包含 names1 和 names2 。
BindingPropertyList
:
BindingPropertyList
,
BindingProperty
1. 让 names1 成为 BoundNames 的结果,
其中 BindingPropertyList 是指向的非终结符。
2. 让 names2 成为 BoundNames 的结果,
其中 BindingProperty 是指向的非终结符。
3. 返回 list-concatenation 的结果,
其中包含 names1 和 names2 。
BindingElementList
:
BindingElementList
,
BindingElisionElement
1. 让 names1 成为 BoundNames 的结果,
其中 BindingElementList 是指向的非终结符。
2. 让 names2 成为 BoundNames 的结果,
其中 BindingElisionElement
是指向的非终结符。
3. 返回 list-concatenation 的结果,
其中包含 names1 和 names2 。
BindingElisionElement
:
Elision opt
BindingElement
1. 返回 BoundNames 的结果,
其中 BindingElement 是指向的非终结符。
BindingProperty
:
PropertyName
:
BindingElement
1. 返回 BoundNames 的结果,
其中 BindingElement 是指向的非终结符。
SingleNameBinding
:
BindingIdentifier
Initializer opt
1. 返回 BoundNames 的结果,
其中 BindingIdentifier 是指向的非终结符。
BindingElement
:
BindingPattern
Initializer opt
1. 返回 BoundNames 的结果,
其中 BindingPattern 是指向的非终结符。
ForDeclaration
:
LetOrConst
ForBinding
1. 返回 BoundNames 的结果,
其中 ForBinding
是指向的非终结符。
FunctionDeclaration
:
function
BindingIdentifier
(
FormalParameters
)
{
FunctionBody
}
1. 返回 BoundNames 的结果,
其中 BindingIdentifier 是指向的非终结符。
FunctionDeclaration
:
function
(
FormalParameters
)
{
FunctionBody
}
1. 返回« "*default*" »。
FormalParameters
: [empty]
1. 返回一个新的空List 。
FormalParameters
:
FormalParameterList
,
FunctionRestParameter
1. 将 names1 设置为获取 FormalParameterList
的BoundNames 。
2. 将 names2 设置为获取 FunctionRestParameter
的BoundNames 。
3. 返回 list-concatenation 的结果,即
names1 和 names2 的连接列表。
FormalParameterList
:
FormalParameterList
,
FormalParameter
1. 将 names1 设置为获取 FormalParameterList
的BoundNames 。
2. 将 names2 设置为获取 FormalParameter 的BoundNames 。
3. 返回 list-concatenation 的结果,即
names1 和 names2 的连接列表。
ArrowParameters
:
CoverParenthesizedExpressionAndArrowParameterList
1. 将 formals 设置为由 ArrowFormalParameters
覆盖的CoverParenthesizedExpressionAndArrowParameterList 。
2. 返回 formals 的BoundNames 。
GeneratorDeclaration
:
function
*
BindingIdentifier
(
FormalParameters
)
{
GeneratorBody
}
1. 返回BindingIdentifier 的绑定名称。
GeneratorDeclaration
:
function
*
(
FormalParameters
)
{
GeneratorBody
}
1. 返回"*default*" 。
AsyncGeneratorDeclaration
:
async
function
*
BindingIdentifier
(
FormalParameters
)
{
AsyncGeneratorBody
}
1. 返回BindingIdentifier 的BoundNames 。
AsyncGeneratorDeclaration
:
async
function
*
(
FormalParameters
)
{
AsyncGeneratorBody
}
1. 返回 « "*default*" »。
ClassDeclaration
:
class
BindingIdentifier
ClassTail
1. 返回BoundNames 中的BindingIdentifier 。
ClassDeclaration
:
class
ClassTail
1. 返回 « "*default*" »。
AsyncFunctionDeclaration
:
async
function
BindingIdentifier
(
FormalParameters
)
{
AsyncFunctionBody
}
1. 返回BoundNames 中的BindingIdentifier 。
AsyncFunctionDeclaration
:
async
function
(
FormalParameters
)
{
AsyncFunctionBody
}
1. 返回 « "*default*" »。
CoverCallExpressionAndAsyncArrowHead
:
MemberExpression
Arguments
1. 令head 为被CoverCallExpressionAndAsyncArrowHead 覆盖的AsyncArrowHead 。
2. 返回head 的BoundNames 。
ImportDeclaration
:
import
ImportClause
FromClause
;
1. 返回BoundNames :ImportClause 。
ImportDeclaration
:
import
ModuleSpecifier
;
1. 返回一个新的空List 。
ImportClause
:
ImportedDefaultBinding
,
NameSpaceImport
1. 让names1 为BoundNames :ImportedDefaultBinding 的BoundNames 。
2. 让names2 为BoundNames :NameSpaceImport 的BoundNames 。
3. 返回list-concatenation 的names1 和names2 。
ImportClause
:
ImportedDefaultBinding
,
NamedImports
1. 让names1 为BoundNames :ImportedDefaultBinding 的BoundNames 。
2. 让names2 为BoundNames :NamedImports 的BoundNames 。
3. 返回list-concatenation 的names1 和names2 。
NamedImports
:
{
}
1. 返回一个新的空List 。
ImportsList
:
ImportsList
,
ImportSpecifier
1. 让names1 为BoundNames :ImportsList 的BoundNames 。
2. 让names2 为BoundNames :ImportSpecifier 的BoundNames 。
3. 返回list-concatenation 的names1 和names2 。
ImportSpecifier
:
ModuleExportName
as
ImportedBinding
1. 返回ImportedBinding 的BoundNames 。
ExportDeclaration
:
export
ExportFromClause
FromClause
;
export
NamedExports
;
1. 返回一个新的空List 。
ExportDeclaration
:
export
VariableStatement
1. 返回VariableStatement 的BoundNames 。
ExportDeclaration
:
export
Declaration
1. 返回Declaration 的BoundNames 。
ExportDeclaration
:
export
default
HoistableDeclaration
1. 令declarationNames 为HoistableDeclaration 的BoundNames 。
2.
如果declarationNames 不包含元素"*default*" ,则将"*default*" 添加到declarationNames 中。
3. 返回declarationNames 。
ExportDeclaration
:
export
default
ClassDeclaration
1. 令declarationNames 为ClassDeclaration 的BoundNames 。
2.
如果declarationNames 不包含元素"*default*" ,则将"*default*" 添加到declarationNames 中。
3. 返回declarationNames 。
ExportDeclaration
:
export
default
AssignmentExpression
;
1. 返回« "*default*" »。
8.2.2 静态语义:DeclarationPart
DeclarationPart 是一个语法导向操作,不接受参数并返回一个解析节点(Parse Node)。它根据以下产生式逐段定义:
HoistableDeclaration
: FunctionDeclaration
1. 返回 FunctionDeclaration 。
HoistableDeclaration
: GeneratorDeclaration
1. 返回 GeneratorDeclaration 。
HoistableDeclaration
: AsyncFunctionDeclaration
1. 返回 AsyncFunctionDeclaration 。
HoistableDeclaration
: AsyncGeneratorDeclaration
1. 返回 AsyncGeneratorDeclaration 。
Declaration
: ClassDeclaration
1. 返回 ClassDeclaration 。
Declaration
: LexicalDeclaration
1. 返回 LexicalDeclaration 。
8.2.3 静态语义:IsConstantDeclaration
语法导向操作
IsConstantDeclaration 不接受任何参数,并返回一个布尔值。它在以下产生式上逐段定义:
LexicalDeclaration
:
LetOrConst
BindingList
;
1. 返回 IsConstantDeclaration
的 LetOrConst 。
LetOrConst
:
let
1. 返回 false 。
LetOrConst
:
const
1. 返回 true 。
FunctionDeclaration
:
function
BindingIdentifier
(
FormalParameters
)
{
FunctionBody
}
function
(
FormalParameters
)
{
FunctionBody
}
GeneratorDeclaration
:
function
*
BindingIdentifier
(
FormalParameters
)
{
GeneratorBody
}
function
*
(
FormalParameters
)
{
GeneratorBody
}
AsyncGeneratorDeclaration
:
async
function
*
BindingIdentifier
(
FormalParameters
)
{
AsyncGeneratorBody
}
async
function
*
(
FormalParameters
)
{
AsyncGeneratorBody
}
AsyncFunctionDeclaration
:
async
function
BindingIdentifier
(
FormalParameters
)
{
AsyncFunctionBody
}
async
function
(
FormalParameters
)
{
AsyncFunctionBody
}
1. 返回 false 。
ClassDeclaration
:
class
BindingIdentifier
ClassTail
class
ClassTail
1. 返回 false 。
ExportDeclaration
:
export
ExportFromClause
FromClause
;
export
NamedExports
;
export
default
AssignmentExpression
;
1. 返回 false 。
注
没有必要将 export default
AssignmentExpression
视为常量声明,因为没有语法允许对用于引用模块默认对象的内部绑定名称进行赋值。
8.2.4 静态语义:词法声明的名称
语法导向操作
LexicallyDeclaredNames 不接受任何参数,并返回一个字符串列表 。它在以下产生式上逐段定义:
Block :
{
}
1. 返回一个新的空列表 。
StatementList
:
StatementList
StatementListItem
1. 令 names1 为 LexicallyDeclaredNames
的 StatementList 。
2. 令 names2 为 LexicallyDeclaredNames
的 StatementListItem 。
3. 返回 names1 和 names2 的列表连接 。
StatementListItem
: Statement
1. 如果 Statement 是
Statement
: LabelledStatement
,返回 LexicallyDeclaredNames
的 LabelledStatement 。
2. 返回一个新的空列表 。
StatementListItem
: Declaration
1. 返回 BoundNames 的 Declaration 。
CaseBlock :
{
}
1. 返回一个新的空列表 。
CaseBlock :
{
CaseClauses opt
DefaultClause
CaseClauses opt
}
1. 如果第一个CaseClauses 存在,令names1 为第一个CaseClauses 的LexicallyDeclaredNames 。
2. 否则,令names1 为一个新的空列表 。
3. 令names2 为DefaultClause 的LexicallyDeclaredNames 。
4. 如果第二个CaseClauses 存在,令names3 为第二个CaseClauses 的LexicallyDeclaredNames 。
5. 否则,令names3 为一个新的空列表 。
6. 返回names1 、names2 和names3 的列表连接 。
CaseClauses
:
CaseClauses
CaseClause
1. 令 names1 为 LexicallyDeclaredNames
的 CaseClauses 。
2. 令 names2 为 LexicallyDeclaredNames
的 CaseClause 。
3. 返回 names1 和 names2 的列表连接 。
CaseClause
:
case
Expression
:
StatementList opt
1. 如果StatementList 存在,返回StatementList 的LexicallyDeclaredNames 。
2. 返回一个新的空列表 。
DefaultClause
:
default
:
StatementList opt
1. 如果StatementList 存在,返回StatementList 的LexicallyDeclaredNames 。
2. 返回一个新的空列表 。
LabelledStatement
:
LabelIdentifier
:
LabelledItem
1. 返回LexicallyDeclaredNames 的LabelledItem 。
LabelledItem
: Statement
1. 返回一个新的空列表 。
LabelledItem
: FunctionDeclaration
1. 返回BoundNames 的FunctionDeclaration 。
FunctionStatementList
: [empty]
1. 返回一个新的空列表 。
FunctionStatementList
: StatementList
1. 返回TopLevelLexicallyDeclaredNames 的StatementList 。
ClassStaticBlockStatementList
: [empty]
1. 返回一个新的空列表 。
ClassStaticBlockStatementList
: StatementList
1. 返回TopLevelLexicallyDeclaredNames 的StatementList 。
ConciseBody
: ExpressionBody
1. 返回一个新的空列表 。
AsyncConciseBody
: ExpressionBody
1. 返回一个新的空列表 。
Script :
[empty]
1. 返回一个新的空列表 。
ScriptBody
: StatementList
1. 返回TopLevelLexicallyDeclaredNames 的StatementList 。
注 1
在Script 的顶层,函数声明被视为var声明,而不是词法声明。
注 2
Module 的LexicallyDeclaredNames包括所有导入绑定的名称。
ModuleItemList
:
ModuleItemList
ModuleItem
1. 令 names1 为 LexicallyDeclaredNames
的 ModuleItemList 。
2. 令 names2 为 LexicallyDeclaredNames
的 ModuleItem 。
3. 返回 names1 和 names2 的列表连接 。
ModuleItem
: ImportDeclaration
1. 返回BoundNames 的ImportDeclaration 。
ModuleItem
: ExportDeclaration
1. 如果ExportDeclaration 是export
VariableStatement ,返回一个新的空列表 。
2. 返回BoundNames 的ExportDeclaration 。
ModuleItem
: StatementListItem
1. 返回LexicallyDeclaredNames 的StatementListItem 。
注 3
在Module 的顶层,函数声明被视为词法声明,而不是var声明。
8.2.5 静态语义:词法作用域声明
语法导向操作
LexicallyScopedDeclarations 不接受任何参数,并返回一个列表 ,其中包含解析节点 。它在以下产生式上逐段定义:
StatementList
:
StatementList
StatementListItem
1. 令 declarations1 为 LexicallyScopedDeclarations
的 StatementList 。
2. 令 declarations2 为 LexicallyScopedDeclarations
的 StatementListItem 。
3. 返回 declarations1 和 declarations2 的列表连接 。
StatementListItem
: Statement
1. 如果Statement 是
Statement
:
LabelledStatement
,返回LexicallyScopedDeclarations 的LabelledStatement 。
2. 返回一个新的空列表 。
StatementListItem
: Declaration
1. 返回一个列表 ,其唯一元素是DeclarationPart 的Declaration 。
CaseBlock :
{
}
1. 返回一个新的空列表 。
CaseBlock :
{
CaseClauses opt
DefaultClause
CaseClauses opt
}
1. 如果第一个CaseClauses 存在,令declarations1 为第一个CaseClauses 的LexicallyScopedDeclarations 。
2. 否则,令declarations1 为一个新的空列表 。
3. 令declarations2 为DefaultClause 的LexicallyScopedDeclarations 。
4. 如果第二个CaseClauses 存在,令declarations3 为第二个CaseClauses 的LexicallyScopedDeclarations 。
5. 否则,令declarations3 为一个新的空列表 。
6.
返回declarations1 、declarations2 和declarations3 的列表连接 。
CaseClauses
:
CaseClauses
CaseClause
1. 令 declarations1 为 LexicallyScopedDeclarations
的 CaseClauses 。
2. 令 declarations2 为 LexicallyScopedDeclarations
的 CaseClause 。
3. 返回 declarations1 和 declarations2 的列表连接 。
CaseClause
:
case
Expression
:
StatementList opt
1. 如果StatementList 存在,返回StatementList 的LexicallyScopedDeclarations 。
2. 返回一个新的空列表 。
DefaultClause
:
default
:
StatementList opt
1. 如果StatementList 存在,返回StatementList 的LexicallyScopedDeclarations 。
2. 返回一个新的空列表 。
LabelledStatement
:
LabelIdentifier
:
LabelledItem
1. 返回LexicallyScopedDeclarations 的LabelledItem 。
LabelledItem
: Statement
1. 返回一个新的空列表 。
LabelledItem
: FunctionDeclaration
1. 返回 « FunctionDeclaration »。
FunctionStatementList
: [empty]
1. 返回一个新的空列表 。
FunctionStatementList
: StatementList
1. 返回TopLevelLexicallyScopedDeclarations 的StatementList 。
ClassStaticBlockStatementList
: [empty]
1. 返回一个新的空列表 。
ClassStaticBlockStatementList
: StatementList
1. 返回TopLevelLexicallyScopedDeclarations 的StatementList 。
ConciseBody
: ExpressionBody
1. 返回一个新的空列表 。
AsyncConciseBody
: ExpressionBody
1. 返回一个新的空列表 。
Script :
[empty]
1. 返回一个新的空列表 。
ScriptBody
: StatementList
1. 返回TopLevelLexicallyScopedDeclarations 的StatementList 。
Module :
[empty]
1. 返回一个新的空列表 。
ModuleItemList
:
ModuleItemList
ModuleItem
1. 令 declarations1 为 LexicallyScopedDeclarations
的 ModuleItemList 。
2. 令 declarations2 为 LexicallyScopedDeclarations
的 ModuleItem 。
3. 返回 declarations1 和 declarations2 的列表连接 。
ModuleItem
: ImportDeclaration
1. 返回一个新的空列表 。
ExportDeclaration
:
export
ExportFromClause
FromClause
;
export
NamedExports
;
export
VariableStatement
1. 返回一个新的空列表 。
ExportDeclaration
:
export
Declaration
1. 返回一个列表 ,其唯一元素是DeclarationPart 的Declaration 。
ExportDeclaration
:
export
default
HoistableDeclaration
1. 返回一个列表 ,其唯一元素是DeclarationPart 的HoistableDeclaration 。
ExportDeclaration
:
export
default
ClassDeclaration
1. 返回一个列表 ,其唯一元素是ClassDeclaration 。
ExportDeclaration
:
export
default
AssignmentExpression
;
1. 返回一个列表 ,其唯一元素是此ExportDeclaration 。
8.2.6 静态语义: VarDeclaredNames
语法导向操作
VarDeclaredNames 不接受任何参数,并返回一个字符串列表 。它在以下产生式上逐段定义:
Statement :
EmptyStatement
ExpressionStatement
ContinueStatement
BreakStatement
ReturnStatement
ThrowStatement
DebuggerStatement
1. 返回一个新的空列表 。
Block :
{
}
1. 返回一个新的空列表 。
StatementList
:
StatementList
StatementListItem
1. 令 names1 为 VarDeclaredNames
的 StatementList 。
2. 令 names2 为 VarDeclaredNames
的 StatementListItem 。
3. 返回 names1 和 names2 的列表连接 。
StatementListItem
: Declaration
1. 返回一个新的空列表 。
VariableStatement
:
var
VariableDeclarationList
;
1. 返回BoundNames 的VariableDeclarationList 。
IfStatement
:
if
(
Expression
)
Statement
else
Statement
1. 令 names1 为第一个VarDeclaredNames
的Statement 。
2. 令 names2 为第二个VarDeclaredNames
的Statement 。
3. 返回 names1 和 names2 的列表连接 。
IfStatement
:
if
(
Expression
)
Statement
1. 返回VarDeclaredNames 的Statement 。
DoWhileStatement
:
do
Statement
while
(
Expression
)
;
1. 返回VarDeclaredNames 的Statement 。
WhileStatement
:
while
(
Expression
)
Statement
1. 返回VarDeclaredNames 的Statement 。
ForStatement
:
for
(
Expression opt
;
Expression opt
;
Expression opt
)
Statement
1. 返回VarDeclaredNames 的Statement 。
ForStatement
:
for
(
var
VariableDeclarationList
;
Expression opt
;
Expression opt
)
Statement
1. 令 names1 为 BoundNames 的 VariableDeclarationList 。
2. 令 names2 为 VarDeclaredNames
的 Statement 。
3. 返回 names1 和 names2 的列表连接 。
ForStatement
:
for
(
LexicalDeclaration
Expression opt
;
Expression opt
)
Statement
1. 返回VarDeclaredNames 的Statement 。
ForInOfStatement
:
for
(
LeftHandSideExpression
in
Expression
)
Statement
for
(
ForDeclaration
in
Expression
)
Statement
for
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
for
(
ForDeclaration
of
AssignmentExpression
)
Statement
for
await
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
for
await
(
ForDeclaration
of
AssignmentExpression
)
Statement
1. 返回VarDeclaredNames 的Statement 。
ForInOfStatement
:
for
(
var
ForBinding
in
Expression
)
Statement
for
(
var
ForBinding
of
AssignmentExpression
)
Statement
for
await
(
var
ForBinding
of
AssignmentExpression
)
Statement
1. 令 names1 为 BoundNames 的 ForBinding 。
2. 令 names2 为 VarDeclaredNames
的 Statement 。
3. 返回 names1 和 names2 的列表连接 。
注
WithStatement
:
with
(
Expression
)
Statement
1. 返回VarDeclaredNames 的Statement 。
SwitchStatement
:
switch
(
Expression
)
CaseBlock
1. 返回VarDeclaredNames 的CaseBlock 。
CaseBlock :
{
}
1. 返回一个新的空列表 。
CaseBlock :
{
CaseClauses opt
DefaultClause
CaseClauses opt
}
1. 如果第一个CaseClauses 存在,令names1 为第一个CaseClauses 的VarDeclaredNames 。
2. 否则,令names1 为一个新的空列表 。
3. 令names2 为DefaultClause 的VarDeclaredNames 。
4. 如果第二个CaseClauses 存在,令names3 为第二个CaseClauses 的VarDeclaredNames 。
5. 否则,令names3 为一个新的空列表 。
6. 返回names1 、names2 和names3 的列表连接 。
CaseClauses
:
CaseClauses
CaseClause
1. 令 names1 为 VarDeclaredNames
的 CaseClauses 。
2. 令 names2 为 VarDeclaredNames
的 CaseClause 。
3. 返回 names1 和 names2 的列表连接 。
CaseClause
:
case
Expression
:
StatementList opt
1. 如果StatementList 存在,返回StatementList 的VarDeclaredNames 。
2. 返回一个新的空列表 。
DefaultClause
:
default
:
StatementList opt
1. 如果StatementList 存在,返回StatementList 的VarDeclaredNames 。
2. 返回一个新的空列表 。
LabelledStatement
:
LabelIdentifier
:
LabelledItem
1. 返回VarDeclaredNames 的LabelledItem 。
LabelledItem
: FunctionDeclaration
1. 返回一个新的空列表 。
TryStatement
:
try
Block
Catch
1. 令 names1 为 VarDeclaredNames
的 Block 。
2. 令 names2 为 VarDeclaredNames
的 Catch 。
3. 返回 names1 和 names2 的列表连接 。
TryStatement
:
try
Block
Finally
1. 令 names1 为 VarDeclaredNames
的 Block 。
2. 令 names2 为 VarDeclaredNames
的 Finally 。
3. 返回 names1 和 names2 的列表连接 。
TryStatement
:
try
Block
Catch
Finally
1. 令 names1 为 VarDeclaredNames
的 Block 。
2. 令 names2 为 VarDeclaredNames
的 Catch 。
3. 令 names3 为 VarDeclaredNames
的 Finally 。
4. 返回 names1 、names2 和 names3 的
列表连接 。
Catch :
catch
(
CatchParameter
)
Block
1. 返回VarDeclaredNames 的Block 。
FunctionStatementList
: [empty]
1. 返回一个新的空列表 。
FunctionStatementList
: StatementList
1. 返回TopLevelVarDeclaredNames 的StatementList 。
ClassStaticBlockStatementList
:
[empty]
1. 返回一个新的空列表 。
ClassStaticBlockStatementList
:
StatementList
1. 返回TopLevelVarDeclaredNames 的StatementList 。
ConciseBody
:
ExpressionBody
1. 返回一个新的空列表 。
AsyncConciseBody
:
ExpressionBody
1. 返回一个新的空列表 。
Script
:
[empty]
1. 返回一个新的空列表 。
ScriptBody
:
StatementList
1. 返回TopLevelVarDeclaredNames 的StatementList 。
ModuleItemList
:
ModuleItemList
ModuleItem
1. 令 names1 为 VarDeclaredNames
的 ModuleItemList 。
2. 令 names2 为 VarDeclaredNames
的 ModuleItem 。
3. 返回 names1 和 names2 的 列表连接 。
ModuleItem
:
ImportDeclaration
1. 返回一个新的空列表 。
ModuleItem
:
ExportDeclaration
1. 如果ExportDeclaration 是export
VariableStatement ,返回BoundNames 的ExportDeclaration 。
2. 返回一个新的空列表 。
8.2.7 静态语义:VarScopedDeclarations
VarScopedDeclarations是一个无需参数并返回List 的语法定向操作,其中列表包含Parse Nodes 。它通过以下各个产生式逐段定义:
Statement :
EmptyStatement
ExpressionStatement
ContinueStatement
BreakStatement
ReturnStatement
ThrowStatement
DebuggerStatement
1. 返回一个新的空 List 。
Block :
{
}
1. 返回一个新的空 List 。
StatementList
:
StatementList
StatementListItem
1. 令 declarations1 为 VarScopedDeclarations ,位于
StatementList 。
2. 令 declarations2 为 VarScopedDeclarations ,位于
StatementListItem 。
3. 返回 list-concatenation 的结果,包括
declarations1 和 declarations2 。
StatementListItem
: Declaration
1. 返回一个新的空 List 。
VariableDeclarationList
: VariableDeclaration
1. 返回 « VariableDeclaration »。
VariableDeclarationList
:
VariableDeclarationList
,
VariableDeclaration
1. 令 declarations1 为 VarScopedDeclarations
的 VariableDeclarationList 。
2. 返回 list-concatenation 的
declarations1 和 « VariableDeclaration »。
IfStatement
:
if
(
Expression
)
Statement
else
Statement
1. 令 declarations1 为 VarScopedDeclarations
的第一个 Statement 。
2. 令 declarations2 为 VarScopedDeclarations
的第二个 Statement 。
3. 返回 list-concatenation 的
declarations1 和 declarations2 。
IfStatement
:
if
(
Expression
)
Statement
1. 返回 Statement
的 VarScopedDeclarations 。
DoWhileStatement
:
do
Statement
while
(
Expression
)
;
1. 返回 Statement
的 VarScopedDeclarations 。
WhileStatement
:
while
(
Expression
)
Statement
1. 返回 Statement
的 VarScopedDeclarations 。
ForStatement
:
for
(
Expression opt
;
Expression opt
;
Expression opt
)
Statement
1. 返回 Statement
的 VarScopedDeclarations 。
ForStatement
:
for
(
var
VariableDeclarationList
;
Expression opt
;
Expression opt
)
Statement
1. 让 declarations1 成为 VariableDeclarationList
的 VarScopedDeclarations 。
2. 让 declarations2 成为 Statement
的 VarScopedDeclarations 。
3. 返回 declarations1 和 declarations2 的 list-concatenation 。
ForStatement
:
for
(
LexicalDeclaration
Expression opt
;
Expression opt
)
Statement
1. 返回 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
1. 返回 Statement 的 VarScopedDeclarations 。
ForInOfStatement
:
for
(
var
ForBinding
in
Expression
)
Statement
for
(
var
ForBinding
of
AssignmentExpression
)
Statement
for
await
(
var
ForBinding
of
AssignmentExpression
)
Statement
1. 令 declarations1 为 « ForBinding »。
2. 令 declarations2 为 VarScopedDeclarations
在 Statement
中的结果。
3. 返回 declarations1 和 declarations2 的 list-concatenation 。
注
WithStatement
:
with
(
Expression
)
Statement
1. 返回VarScopedDeclarations
Statement 的内容。
SwitchStatement
:
switch
(
Expression
)
CaseBlock
返回 VarScopedDeclarations 的 CaseBlock 。
CaseBlock :
{
}
1. 返回一个新的空列表 。
CaseBlock :
{
CaseClauses opt
DefaultClause
CaseClauses opt
}
1. 如果第一个CaseClauses 存在,则让declarations1 成为第一个CaseClauses 的VarScopedDeclarations 。
2. 否则,让declarations1 成为一个新的空列表 。
3. 让declarations2 成为VarScopedDeclarations 的DefaultClause 。
4. 如果第二个CaseClauses 存在,则让declarations3 成为第二个CaseClauses 的VarScopedDeclarations 。
5. 否则,让declarations3 成为一个新的空列表 。
6.
返回declarations1 ,declarations2 和declarations3 的列表连接 。
CaseClauses
:
CaseClauses
CaseClause
1. 让declarations1 成为VarScopedDeclarations 的CaseClauses 。
2. 让declarations2 成为VarScopedDeclarations 的CaseClause 。
3. 返回declarations1 和declarations2 的列表连接 。
CaseClause
:
case
Expression
:
StatementList opt
1. 如果StatementList 存在,
返回VarScopedDeclarations 的StatementList 。
2. 返回一个新的空List 。
DefaultClause
:
default
:
StatementList opt
1. 如果StatementList 存在,
返回VarScopedDeclarations 的StatementList 。
2. 返回一个新的空List 。
LabelledStatement
:
LabelIdentifier
:
LabelledItem
1. 返回VarScopedDeclarations
的LabelledItem 。
LabelledItem
: FunctionDeclaration
1. 返回一个新的空List 。
TryStatement
:
try
Block
Catch
1. 让declarations1 为VarScopedDeclarations
的Block 。
2. 让declarations2 为VarScopedDeclarations
的Catch 。
3. 返回declarations1 和declarations2 的list-concatenation 。
TryStatement
:
try
Block
Finally
1. 将declarations1 设为Block 的变量作用域声明。
2. 将declarations2 设为Finally 的变量作用域声明。
3. 返回declarations1 和declarations2 的列表连接 。
TryStatement
:
try
Block
Catch
Finally
1. 将declarations1 设为Block 的变量作用域声明。
2. 将declarations2 设为Catch 的变量作用域声明。
3. 将declarations3 设为Finally 的变量作用域声明。
4.
返回declarations1 、declarations2 和declarations3 的列表连接 。
Catch :
catch
(
CatchParameter
)
Block
1. 返回VarScopedDeclarations
的Block 。
FunctionStatementList
: [empty]
1. 返回一个新的空List 。
FunctionStatementList
: StatementList
1. 返回TopLevelVarScopedDeclarations
的StatementList 。
ClassStaticBlockStatementList
: [empty]
1. 返回一个新的空List 。
ClassStaticBlockStatementList
: StatementList
1. 返回TopLevelVarScopedDeclarations
的StatementList 。
ConciseBody
: ExpressionBody
1. 返回一个新的空List 。
AsyncConciseBody
: ExpressionBody
1. 返回一个新的空List 。
Script :
[empty]
1. 返回一个新的空List 。
ScriptBody
: StatementList
1. 返回TopLevelVarScopedDeclarations
的StatementList 。
Module :
[empty]
1. 返回一个新的空List 。
ModuleItemList
:
ModuleItemList
ModuleItem
1. 让declarations1 成为VarScopedDeclarations
的ModuleItemList 。
2. 让declarations2 成为VarScopedDeclarations
的ModuleItem 。
3. 返回list-concatenation 的declarations1 和declarations2 。
ModuleItem
: ImportDeclaration
1. 返回一个新的空List 。
ModuleItem
: ExportDeclaration
1. 如果ExportDeclaration 是
export
VariableStatement ,返回
VarScopedDeclarations
的VariableStatement 。
2. 返回一个新的空List 。
8.2.8 静态语义: TopLevelLexicallyDeclaredNames
语法定向操作
TopLevelLexicallyDeclaredNames 不接受参数并返回一个 字符串列表 。它在以下产生式上被分段定义:
StatementList
:
StatementList
StatementListItem
1. 将names1 设为StatementList 的顶层词法声明名称。
2. 将names2 设为StatementListItem 的顶层词法声明名称。
3. 返回names1 和names2 的列表连接 。
StatementListItem
: Statement
1. 返回一个新的空List 。
StatementListItem
: Declaration
1. 如果Declaration 是
Declaration
: HoistableDeclaration
,则
a. 返回一个新的空List 。
2. 返回BoundNames ,属于Declaration 。
注
在函数或脚本的顶层,函数声明被视为 var 声明,而不是词法声明。
8.2.9 静态语义: TopLevelLexicallyScopedDeclarations
静态语义操作 TopLevelLexicallyScopedDeclarations 不接受参数,并返回一个 List ,其中包含
解析节点 。它根据以下产生式逐段定义:
StatementList
:
StatementList
StatementListItem
1. 让 declarations1 成为 TopLevelLexicallyScopedDeclarations
的 StatementList 。
2. 让 declarations2 成为 TopLevelLexicallyScopedDeclarations
的 StatementListItem 。
3. 返回 list-concatenation ,
包含 declarations1 和 declarations2 。
StatementListItem
: Statement
1. 返回一个新的空 List 。
StatementListItem
: Declaration
1. 如果 Declaration 是
Declaration
: HoistableDeclaration
,那么
a. 返回一个新的空 List 。
2. 返回 « Declaration »。
8.2.10 静态语义: TopLevelVarDeclaredNames
语法定向操作 TopLevelVarDeclaredNames 不接受参数,并返回一个 List ,其中包含字符串列表。它在以下产生式上分段定义:
StatementList
:
StatementList
StatementListItem
1. 令 names1 为 TopLevelVarDeclaredNames
是 StatementList 的。
2. 令 names2 为 TopLevelVarDeclaredNames
是 StatementListItem 的。
3. 返回 list-concatenation 的
names1 和 names2 。
StatementListItem
: Declaration
1. 如果 Declaration 是
Declaration
: HoistableDeclaration
,则
a. 返回 BoundNames 的
HoistableDeclaration 。
2. 返回一个新的空 List 。
StatementListItem
: Statement
1. 如果 Statement 是
Statement
: LabelledStatement
,返回 TopLevelVarDeclaredNames
的 Statement 。
2. 返回 VarDeclaredNames
的 Statement 。
注
在函数或脚本的顶层,内部函数声明被视为 var 声明。
LabelledStatement
:
LabelIdentifier
:
LabelledItem
1. 返回 TopLevelVarDeclaredNames
的LabelledItem 。
LabelledItem
: Statement
1. 如果Statement 是
Statement
: LabelledStatement
,返回TopLevelVarDeclaredNames
的Statement 。
2. 返回VarDeclaredNames
的Statement 。
LabelledItem
: FunctionDeclaration
1. 返回FunctionDeclaration 的FunctionDeclaration 。
8.2.11 Static Semantics: TopLevelVarScopedDeclarations
The 语法导向操作
TopLevelVarScopedDeclarations
不接受参数并返回一个 列表 ,其中包含
解析节点 。
它在以下各处生效:
StatementList
:
StatementList
StatementListItem
1. Let declarations1 be TopLevelVarScopedDeclarations
的StatementList 。
2. Let declarations2 be TopLevelVarScopedDeclarations
的StatementListItem 。
3. Return 列表连接 declarations1
和
declarations2 。
StatementListItem
: Statement
1. 如果 Statement 是
Statement
: LabelledStatement
,返回 TopLevelVarScopedDeclarations
的Statement 。
2. 返回 VarScopedDeclarations
的Statement 。
StatementListItem
: Declaration
1. 如果 Declaration 是
Declaration
: HoistableDeclaration
,那么
a. 让 declaration 成为 HoistableDeclaration
的DeclarationPart 。
b. 返回 « declaration »。
2. 返回一个新的空 List 。
LabelledStatement
:
LabelIdentifier
:
LabelledItem
1. 返回 TopLevelVarScopedDeclarations
中的 LabelledItem 。
LabelledItem
: Statement
1. 如果 Statement 是
Statement
: LabelledStatement
, 返回 TopLevelVarScopedDeclarations
中的 Statement 。
2. 返回 VarScopedDeclarations
中的 Statement 。
LabelledItem
: FunctionDeclaration
1. 返回 « FunctionDeclaration »。
8.3 Labels
8.3.1 静态语义: 包含重复标签 (ContainsDuplicateLabels)
语法导向操作
ContainsDuplicateLabels 接受参数 labelSet (一个 字符串列表 )并返回一个布尔值。它在以下各个产生式上分段定义:
Statement :
VariableStatement
EmptyStatement
ExpressionStatement
ContinueStatement
BreakStatement
ReturnStatement
ThrowStatement
DebuggerStatement
Block :
{
}
StatementListItem
:
Declaration
1. 返回 false 。
StatementList
:
StatementList
StatementListItem
1. 令 hasDuplicates 为带有参数 labelSet 的 ContainsDuplicateLabels
在 StatementList 中的结果。
2. 如果 hasDuplicates 是 true ,则返回
true 。
3. 返回带有参数 labelSet 的 ContainsDuplicateLabels
在 StatementListItem 中的结果。
IfStatement
:
if
(
Expression
)
Statement
else
Statement
1. 令 hasDuplicate 为带有参数 labelSet 的 ContainsDuplicateLabels
在第一个 Statement
中的结果。
2. 如果 hasDuplicate 是 true ,则返回
true 。
3. 返回带有参数 labelSet 的 ContainsDuplicateLabels
在第二个 Statement
中的结果。
IfStatement
:
if
(
Expression
)
Statement
1. 返回带有参数 labelSet 的 ContainsDuplicateLabels
在 Statement
中的结果。
DoWhileStatement
:
do
Statement
while
(
Expression
)
;
1. 返回带有参数 labelSet 的 ContainsDuplicateLabels
在 Statement
中的结果。
WhileStatement
:
while
(
Expression
)
Statement
1. 返回带有参数 labelSet 的 ContainsDuplicateLabels
在 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
1. 返回带有参数 labelSet 的 ContainsDuplicateLabels
在 Statement
中的结果。
ForInOfStatement
:
for
(
LeftHandSideExpression
in
Expression
)
Statement
for
(
var
ForBinding
in
Expression
)
Statement
for
(
ForDeclaration
in
Expression
)
Statement
for
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
for
(
var
ForBinding
of
AssignmentExpression
)
Statement
for
(
ForDeclaration
of
AssignmentExpression
)
Statement
for
await
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
for
await
(
var
ForBinding
of
AssignmentExpression
)
Statement
for
await
(
ForDeclaration
of
AssignmentExpression
)
Statement
1. 返回带有参数 labelSet 的 ContainsDuplicateLabels
在 Statement
中的结果。
注
WithStatement
:
with
(
Expression
)
Statement
1. 返回带有参数 labelSet 的ContainsDuplicateLabels
的Statement 。
SwitchStatement
:
switch
(
Expression
)
CaseBlock
1. 返回带有参数 labelSet 的ContainsDuplicateLabels
的CaseBlock 。
CaseBlock :
{
}
1. 返回 false 。
CaseBlock :
{
CaseClauses opt
DefaultClause
CaseClauses opt
}
1. 如果第一个 CaseClauses 存在,则
a. 如果使用参数 labelSet 调用第一个 CaseClauses 的 ContainsDuplicateLabels
返回 true ,则返回 true 。
2. 如果使用参数 labelSet 调用 ContainsDuplicateLabels
返回第二个 DefaultClause
的结果为 true ,则返回 true 。
3. 如果第二个 CaseClauses 不存在,则返回
false 。
4. 返回使用参数 labelSet 调用第二个 CaseClauses 的 ContainsDuplicateLabels 。
CaseClauses
:
CaseClauses
CaseClause
1. 令 hasDuplicates 为使用参数 labelSet 调用 ContainsDuplicateLabels
的结果,作用于 CaseClauses 。
2. 如果 hasDuplicates 为 true ,则返回
true 。
3. 返回使用参数 labelSet 调用 ContainsDuplicateLabels
的结果,作用于 CaseClause 。
CaseClause
:
case
Expression
:
StatementList opt
1. 如果存在 StatementList ,则返回使用参数
labelSet 调用
ContainsDuplicateLabels
的结果,作用于 StatementList 。
2. 返回 false 。
DefaultClause
:
default
:
StatementList opt
1. 如果存在 StatementList ,则返回使用参数
labelSet 调用
ContainsDuplicateLabels
的结果,作用于 StatementList 。
2. 返回 false 。
LabelledStatement
:
LabelIdentifier
:
LabelledItem
1. 将 label 设置为 StringValue 的值,来源于
LabelIdentifier 。
2. 如果 labelSet 包含 label ,则返回
true 。
3. 令 newLabelSet 为 list-concatenation ,包含
labelSet 和
« label »。
4. 返回使用参数 newLabelSet 调用 ContainsDuplicateLabels
的结果,作用于 LabelledItem 。
LabelledItem
: FunctionDeclaration
1. 返回 false 。
TryStatement
:
try
Block
Catch
1. 让 hasDuplicates 成为 ContainsDuplicateLabels
用参数 labelSet 计算 Block 。
2. 如果 hasDuplicates 是 true ,则返回
true 。
3. 返回 ContainsDuplicateLabels
用参数 labelSet 计算 Catch 。
TryStatement
:
try
Block
Finally
1. 让 hasDuplicates 成为 ContainsDuplicateLabels
用参数 labelSet 计算 Block 。
2. 如果 hasDuplicates 是 true ,则返回
true 。
3. 返回 ContainsDuplicateLabels
用参数 labelSet 计算 Finally 。
TryStatement
:
try
Block
Catch
Finally
1. 如果 ContainsDuplicateLabels
用参数 labelSet 计算 Block
的结果是 true ,则返回 true 。
2. 如果 ContainsDuplicateLabels
用参数 labelSet 计算 Catch
的结果是 true ,则返回 true 。
3. 返回 ContainsDuplicateLabels
用参数 labelSet 计算 Finally
的结果。
Catch :
catch
(
CatchParameter
)
Block
1. 返回 ContainsDuplicateLabels
用参数 labelSet 计算 Block
的结果。
FunctionStatementList
: [empty]
1. 返回 false 。
ClassStaticBlockStatementList
: [empty]
1. 返回 false .
ModuleItemList
:
ModuleItemList
ModuleItem
1. 令 hasDuplicates 为带有参数 labelSet 的 ContainsDuplicateLabels ,
其中 ModuleItemList
。
2. 如果 hasDuplicates 为 true ,则返回
true 。
3. 返回带有参数 labelSet 的 ContainsDuplicateLabels
,其对应 ModuleItem 。
ModuleItem
:
ImportDeclaration
ExportDeclaration
1. 返回 false 。
8.3.2 静态语义: ContainsUndefinedBreakTarget
语法定向操作 ContainsUndefinedBreakTarget 接受参数 labelSet (一个字符串列表 )并返回一个布尔值。它根据以下产生式逐段定义:
Statement :
VariableStatement
EmptyStatement
ExpressionStatement
ContinueStatement
ReturnStatement
ThrowStatement
DebuggerStatement
Block :
{
}
StatementListItem
:
Declaration
1. 返回 false 。
StatementList
:
StatementList
StatementListItem
1. 让 hasUndefinedLabels 成为 ContainsUndefinedBreakTarget
应用于参数为 labelSet 的 StatementList 。
2. 如果 hasUndefinedLabels 是 true ,则返回
true 。
3. 返回 ContainsUndefinedBreakTarget
应用于参数为 labelSet 的 StatementListItem 。
IfStatement
:
if
(
Expression
)
Statement
else
Statement
1. 让 hasUndefinedLabels 成为 ContainsUndefinedBreakTarget
应用于参数为 labelSet 的第一个 Statement 。
2. 如果 hasUndefinedLabels 是 true ,则返回
true 。
3. 返回 ContainsUndefinedBreakTarget
应用于参数为 labelSet 的第二个 Statement 。
IfStatement
:
if
(
Expression
)
Statement
1. 返回 ContainsUndefinedBreakTarget
应用于参数为 labelSet 的 Statement 。
DoWhileStatement
:
do
Statement
while
(
Expression
)
;
1. 返回 ContainsUndefinedBreakTarget
应用于参数为 labelSet 的 Statement 。
WhileStatement
:
while
(
Expression
)
Statement
1. 返回 ContainsUndefinedBreakTarget
应用于参数为 labelSet 的 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
1. 返回 ContainsUndefinedBreakTarget
应用于参数为 labelSet 的 Statement 。
ForInOfStatement
:
for
(
LeftHandSideExpression
in
Expression
)
Statement
for
(
var
ForBinding
in
Expression
)
Statement
for
(
ForDeclaration
in
Expression
)
Statement
for
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
for
(
var
ForBinding
of
AssignmentExpression
)
Statement
for
(
ForDeclaration
of
AssignmentExpression
)
Statement
for
await
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
for
await
(
var
ForBinding
of
AssignmentExpression
)
Statement
for
await
(
ForDeclaration
of
AssignmentExpression
)
Statement
1. 返回 ContainsUndefinedBreakTarget
应用于参数为 labelSet 的 Statement 。
注
BreakStatement
:
break
;
1. 返回 false 。
BreakStatement
:
break
LabelIdentifier
;
1. 如果 labelSet 不包含 StringValue 的
LabelIdentifier ,则返回
true 。
2. 返回 false 。
WithStatement
:
with
(
Expression
)
Statement
1. 返回 ContainsUndefinedBreakTarget
应用于参数为 labelSet 的 Statement 。
SwitchStatement
:
switch
(
Expression
)
CaseBlock
1. 返回 ContainsUndefinedBreakTarget
应用于参数为 labelSet 的 CaseBlock 。
CaseBlock :
{
}
1. 返回false 。
CaseBlock :
{
CaseClauses opt
DefaultClause
CaseClauses opt
}
1. 如果第一个CaseClauses 存在,则
a. 如果使用参数labelSet 调用ContainsUndefinedBreakTarget
返回true 。
2. 如果使用参数labelSet 调用ContainsUndefinedBreakTarget
的返回值为true ,则返回true 。
3. 如果第二个CaseClauses 不存在,则返回false 。
4. 返回使用参数labelSet 调用ContainsUndefinedBreakTarget
的第二个CaseClauses 。
CaseClauses
:
CaseClauses
CaseClause
1. 令hasUndefinedLabels 为ContainsUndefinedBreakTarget
的返回值,使用参数labelSet 调用CaseClauses 。
2.
如果hasUndefinedLabels 为true ,则返回true 。
3. 使用参数labelSet 调用ContainsUndefinedBreakTarget
的返回值,使用CaseClause 。
CaseClause
:
case
Expression
:
StatementList opt
1. 如果存在StatementList ,则返回使用参数labelSet 调用ContainsUndefinedBreakTarget
的返回值,使用StatementList 。
2. 返回false 。
DefaultClause
:
default
:
StatementList opt
1. 如果StatementList 存在,
使用参数labelSet 调用ContainsUndefinedBreakTarget 的返回值,使用StatementList 。
2. 返回false 。
LabelledStatement
:
LabelIdentifier
:
LabelledItem
1. 令label 为StringValue 的返回值,
使用LabelIdentifier 。
2. 令newLabelSet 为list-concatenation 的返回值,使用labelSet 和«label »。
3. 使用参数newLabelSet 调用ContainsUndefinedBreakTarget 的返回值,
使用LabelledItem 。
LabelledItem
: FunctionDeclaration
1. 返回false 。
TryStatement
:
try
Block
Catch
1. 令hasUndefinedLabels 为ContainsUndefinedBreakTarget 的返回值,
使用Block 和labelSet 。
2.
如果hasUndefinedLabels 为true ,返回true 。
3. 使用Catch 和labelSet 调用ContainsUndefinedBreakTarget 的返回值。
TryStatement
:
try
Block
Finally
1. 令hasUndefinedLabels 为ContainsUndefinedBreakTarget 的返回值,
使用Block 和labelSet 。
2.
如果hasUndefinedLabels 为true ,返回true 。
3. 使用Finally 和labelSet 调用ContainsUndefinedBreakTarget 的返回值。
TryStatement
:
try
Block
Catch
Finally
1. 如果ContainsUndefinedBreakTarget
的返回值为true ,使用Block 和labelSet ,返回true 。
2. 如果ContainsUndefinedBreakTarget
的返回值为true ,使用Catch 和labelSet ,返回true 。
3. 使用Finally 和labelSet 调用ContainsUndefinedBreakTarget 的返回值。
Catch :
catch
(
CatchParameter
)
Block
1. 使用Block 和labelSet 调用ContainsUndefinedBreakTarget 的返回值。
FunctionStatementList
: [空]
1. 返回false 。
ClassStaticBlockStatementList
: [空]
1. 返回false 。
ModuleItemList
:
ModuleItemList
ModuleItem
1. 让hasUndefinedLabels 为ContainsUndefinedBreakTarget
的返回值,使用ModuleItemList 和labelSet 作为参数。
2.
如果hasUndefinedLabels 为true ,返回true 。
3. 使用ModuleItem 和labelSet 作为参数,调用ContainsUndefinedBreakTarget 的返回值。
ModuleItem
:
ImportDeclaration
ExportDeclaration
1. 返回false 。
8.3.3 静态语义: ContainsUndefinedContinueTarget
语法定向操作 ContainsUndefinedContinueTarget 接受参数 iterationSet (一个字符串列表 )和
labelSet (一个字符串列表 ),返回一个布尔值。它根据以下产生式逐段定义:
Statement :
VariableStatement
EmptyStatement
ExpressionStatement
BreakStatement
ReturnStatement
ThrowStatement
DebuggerStatement
Block :
{
}
StatementListItem
:
Declaration
1. 返回 false 。
Statement :
BlockStatement
1. 返回 ContainsUndefinedContinueTarget
对于 BlockStatement 的结果,参数为
iterationSet 和 « »。
BreakableStatement
: IterationStatement
1. 令 newIterationSet 为 list-concatenation 的结果,参数为
iterationSet 和 labelSet 。
2. 返回 ContainsUndefinedContinueTarget
对于 IterationStatement 的结果,参数为
newIterationSet 和 « »。
StatementList
:
StatementList
StatementListItem
1. 令 hasUndefinedLabels 为 ContainsUndefinedContinueTarget
对于 StatementList 的结果,参数为
iterationSet 和 « »。
2. 如果 hasUndefinedLabels 是 true ,则返回
true 。
3. 返回 ContainsUndefinedContinueTarget
对于第二个 Statement
的结果,参数为 iterationSet 和 « »。
IfStatement
:
if
(
Expression
)
Statement
else
Statement
1. 令 hasUndefinedLabels 为 ContainsUndefinedContinueTarget
对于第一个 Statement
的结果,参数为 iterationSet 和 « »。
2. 如果 hasUndefinedLabels 是 true ,则返回
true 。
3. 返回 ContainsUndefinedContinueTarget
对于第二个 Statement
的结果,参数为 iterationSet 和 « »。
IfStatement
:
if
(
Expression
)
Statement
1. 返回 ContainsUndefinedContinueTarget
对于 Statement
的结果,参数为 iterationSet 和 « »。
DoWhileStatement
:
do
Statement
while
(
Expression
)
;
1. 返回 ContainsUndefinedContinueTarget
对于 Statement
的结果,参数为 iterationSet 和 « »。
WhileStatement
:
while
(
Expression
)
Statement
1. 返回 ContainsUndefinedContinueTarget
对于 Statement
的结果,参数为 iterationSet 和 « »。
ForStatement
:
for
(
Expression opt
;
Expression opt
;
Expression opt
)
Statement
for
(
var
VariableDeclarationList
;
Expression opt
;
Expression opt
)
Statement
for
(
LexicalDeclaration
Expression opt
;
Expression opt
)
Statement
1. 返回使用参数 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
对 Statement
进行调用。
ForInOfStatement
:
for
(
LeftHandSideExpression
in
Expression
)
Statement
for
(
var
ForBinding
in
Expression
)
Statement
for
(
ForDeclaration
in
Expression
)
Statement
for
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
for
(
var
ForBinding
of
AssignmentExpression
)
Statement
for
(
ForDeclaration
of
AssignmentExpression
)
Statement
for
await
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
for
await
(
var
ForBinding
of
AssignmentExpression
)
Statement
for
await
(
ForDeclaration
of
AssignmentExpression
)
Statement
1. 返回使用参数 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
对 Statement
进行调用。
注
ContinueStatement
:
continue
;
1. 返回 false 。
ContinueStatement
:
continue
LabelIdentifier
;
1. 如果 iterationSet 不包含 LabelIdentifier 的 StringValue ,则返回
true 。
2. 返回 false 。
WithStatement
:
with
(
Expression
)
Statement
1. 返回使用参数 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
对 Statement
进行调用。
SwitchStatement
:
switch
(
Expression
)
CaseBlock
1. 返回使用参数 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
对 CaseBlock
进行调用。
CaseBlock :
{
}
1. 返回 false 。
CaseBlock :
{
CaseClauses opt
DefaultClause
CaseClauses opt
}
1. 如果第一个 CaseClauses 存在,则
a. 如果 ContainsUndefinedContinueTarget
对第一个带参数 iterationSet 和 « » 的 CaseClauses 返回
true ,则返回 true 。
2. 如果 ContainsUndefinedContinueTarget
对带参数 iterationSet 和 « » 的 DefaultClause 返回
true ,则返回 true 。
3. 如果第二个 CaseClauses 不存在,则返回
false 。
4. 返回使用参数 iterationSet 和 « » 的第二个 CaseClauses 的
ContainsUndefinedContinueTarget 。
CaseClauses
:
CaseClauses
CaseClause
1. 令 hasUndefinedLabels 等于使用参数 iterationSet 和
« » 的 ContainsUndefinedContinueTarget
对 CaseClauses
进行调用。
2. 如果 hasUndefinedLabels 是 true ,则返回
true 。
3. 返回使用参数 iterationSet 和 « » 的 ContainsUndefinedContinueTarget
对 CaseClause
进行调用。
CaseClause
:
case
Expression
:
StatementList opt
1. 如果存在 StatementList ,则返回使用参数
iterationSet 和 « » 的
ContainsUndefinedContinueTarget
对 StatementList 进行调用。
2. 返回 false 。
DefaultClause
:
default
:
StatementList opt
1. 如果存在 StatementList ,则返回使用参数
iterationSet 和 « » 的
ContainsUndefinedContinueTarget
对 StatementList 进行调用。
2. 返回 false 。
LabelledStatement
:
LabelIdentifier
:
LabelledItem
1. 令 label 为 LabelIdentifier 的 StringValue 。
2. 令 newLabelSet 为 labelSet 和 «
label » 的
list-concatenation 。
3. 返回使用参数 iterationSet 和 newLabelSet 的 ContainsUndefinedContinueTarget
对 LabelledItem 进行调用。
LabelledItem
: FunctionDeclaration
1. 返回 false 。
TryStatement
:
try
Block
Catch
1. 令 hasUndefinedLabels 为使用参数 iterationSet 和
« »
调用 ContainsUndefinedContinueTarget
对 Block 的结果。
2. 如果 hasUndefinedLabels 是 true ,则返回
true 。
3. 返回使用参数 iterationSet 和 « » 调用 ContainsUndefinedContinueTarget
对 Catch 的结果。
TryStatement
:
try
Block
Finally
1. 令 hasUndefinedLabels 为使用参数 iterationSet 和
« »
调用 ContainsUndefinedContinueTarget
对 Block 的结果。
2. 如果 hasUndefinedLabels 是 true ,则返回
true 。
3. 返回使用参数 iterationSet 和 « » 调用 ContainsUndefinedContinueTarget
对 Finally 的结果。
TryStatement
:
try
Block
Catch
Finally
1. 如果使用参数 iterationSet 和 « » 调用 ContainsUndefinedContinueTarget
对 Block 的结果为
true ,则返回
true 。
2. 如果使用参数 iterationSet 和 « » 调用 ContainsUndefinedContinueTarget
对 Catch 的结果为
true ,则返回
true 。
3. 返回使用参数 iterationSet 和 « » 调用 ContainsUndefinedContinueTarget
对 Finally 的结果。
Catch :
catch
(
CatchParameter
)
Block
1. 返回使用参数 iterationSet 和 « » 调用 ContainsUndefinedContinueTarget
对 Block 的结果。
FunctionStatementList
: [empty]
1. 返回 false 。
ClassStaticBlockStatementList
: [empty]
1. 返回 false 。
ModuleItemList
:
ModuleItemList
ModuleItem
1. 让 hasUndefinedLabels 成为使用参数 iterationSet 和
« » 调用 ContainsUndefinedContinueTarget
对 ModuleItemList 的结果。
2. 如果 hasUndefinedLabels 是 true ,则返回
true 。
3. 返回使用参数 iterationSet 和 « » 调用 ContainsUndefinedContinueTarget
对 ModuleItem
的结果。
ModuleItem
:
ImportDeclaration
ExportDeclaration
1. 返回 false 。
8.4 函数名称推断
8.4.1 静态语义:HasName
语法定向操作
HasName 不接受任何参数并返回一个布尔值。它在以下各个生成式上逐块定义:
PrimaryExpression
: CoverParenthesizedExpressionAndArrowParameterList
1. 令 expr 为 ParenthesizedExpression ,它被
CoverParenthesizedExpressionAndArrowParameterList
覆盖 。
2. 如果 expr 的 IsFunctionDefinition
为 false ,则返回 false 。
3. 返回 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
1. 返回 false 。
FunctionExpression
:
function
BindingIdentifier
(
FormalParameters
)
{
FunctionBody
}
GeneratorExpression
:
function
*
BindingIdentifier
(
FormalParameters
)
{
GeneratorBody
}
AsyncGeneratorExpression
:
async
function
*
BindingIdentifier
(
FormalParameters
)
{
AsyncGeneratorBody
}
AsyncFunctionExpression
:
async
function
BindingIdentifier
(
FormalParameters
)
{
AsyncFunctionBody
}
ClassExpression
:
class
BindingIdentifier
ClassTail
1. 返回 true .
8.4.2 静态语义:IsFunctionDefinition
语法导向操作
IsFunctionDefinition 不接受任何参数,返回一个布尔值。它在以下产生式上逐步定义:
PrimaryExpression
: CoverParenthesizedExpressionAndArrowParameterList
1. 令 expr 为 ParenthesizedExpression ,它是由
CoverParenthesizedExpressionAndArrowParameterList
覆盖 的表达式。
2. 返回 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
1. 返回 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
1. 返回 true .
8.4.3 静态语义:IsAnonymousFunctionDefinition ( expr )
抽象操作 IsAnonymousFunctionDefinition 接受参数 expr (一个 AssignmentExpression 解析节点 ,一个 Initializer 解析节点 ,或一个 Expression 解析节点 )并返回一个布尔值。它确定其参数是否为不绑定名称的函数定义。当调用时执行以下步骤:
1. 如果 expr 的 IsFunctionDefinition
返回 false ,则返回 false 。
2. 令 hasName 为 expr 的 HasName 。
3. 如果 hasName 返回 true ,则返回
false 。
4. 返回 true 。
8.4.4 静态语义:IsIdentifierRef
语法定向操作
IsIdentifierRef 不接受任何参数并返回一个布尔值。它在以下各个生成式中逐段定义:
PrimaryExpression
: IdentifierReference
1. 返回 true .
PrimaryExpression
:
this
Literal
ArrayLiteral
ObjectLiteral
FunctionExpression
ClassExpression
GeneratorExpression
AsyncFunctionExpression
AsyncGeneratorExpression
RegularExpressionLiteral
TemplateLiteral
CoverParenthesizedExpressionAndArrowParameterList
MemberExpression
:
MemberExpression
[
Expression
]
MemberExpression
.
IdentifierName
MemberExpression
TemplateLiteral
SuperProperty
MetaProperty
new
MemberExpression
Arguments
MemberExpression
.
PrivateIdentifier
NewExpression
:
new
NewExpression
LeftHandSideExpression
:
CallExpression
OptionalExpression
1. 返回 false .
8.4.5 运行时语义:NamedEvaluation
语法定向操作
NamedEvaluation 接受参数 name (一个 属性键 或一个 私有名称 )并返回一个 包含 一个 函数对象 的正常完成记录或一个 异常完成 。它在以下各个生成式中逐段定义:
PrimaryExpression
: CoverParenthesizedExpressionAndArrowParameterList
1. 令 expr 为 ParenthesizedExpression ,它被
覆盖 在 CoverParenthesizedExpressionAndArrowParameterList
中。
2. 返回 ? NamedEvaluation 以 name 作为参数调用 expr 。
ParenthesizedExpression
:
(
Expression
)
1. 断言 : IsAnonymousFunctionDefinition (Expression ) 为
true 。
2. 返回 ? NamedEvaluation 以 name 作为参数调用 Expression 。
FunctionExpression
:
function
(
FormalParameters
)
{
FunctionBody
}
1. 返回 InstantiateOrdinaryFunctionExpression
以 name 作为参数调用 FunctionExpression 。
GeneratorExpression
:
function
*
(
FormalParameters
)
{
GeneratorBody
}
1. 返回 InstantiateGeneratorFunctionExpression
以 name 作为参数调用 GeneratorExpression 。
AsyncGeneratorExpression
:
async
function
*
(
FormalParameters
)
{
AsyncGeneratorBody
}
1. 返回 InstantiateAsyncGeneratorFunctionExpression
以 name 作为参数调用 AsyncGeneratorExpression 。
AsyncFunctionExpression
:
async
function
(
FormalParameters
)
{
AsyncFunctionBody
}
1. 返回 InstantiateAsyncFunctionExpression
以 name 作为参数调用 AsyncFunctionExpression 。
ArrowFunction
:
ArrowParameters
=>
ConciseBody
1. 返回 InstantiateArrowFunctionExpression
以 name 作为参数调用 ArrowFunction 。
AsyncArrowFunction
:
async
AsyncArrowBindingIdentifier
=>
AsyncConciseBody
CoverCallExpressionAndAsyncArrowHead
=>
AsyncConciseBody
1. 返回 InstantiateAsyncArrowFunctionExpression
以 name 作为参数调用 AsyncArrowFunction 。
ClassExpression
:
class
ClassTail
1. 令 value 为 ? ClassDefinitionEvaluation 以 ClassTail 和参数
undefined 以及 name 调用。
2. 将 value .[[SourceText]] 设置为
与
ClassExpression 匹配的源文本。
3. 返回 value 。
8.5 包含
8.5.1 静态语义:Contains
语法导向操作
Contains 接受参数 symbol (一个语法符号)并返回一个布尔值。
本规范中未列出的每个语法生成替代方案都隐含具有以下默认的 Contains 定义:
1. 对于此
解析节点 的每个子节点
child ,执行以下操作:
a. 如果 child 是 symbol 的一个实例,返回
true 。
b. 如果 child 是一个非终结符的实例,那么:
i. 令 contained 为 child 结果的
Contains
symbol 。
ii. 如果 contained 是 true ,返回
true 。
2. 返回 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
}
1. 返回 false 。
注 1
依赖于子结构的静态语义规则通常不会深入查看函数定义。
ClassTail :
ClassHeritage opt
{
ClassBody
}
1. 如果 symbol 是 ClassBody ,则返回 true 。
2. 如果 symbol 是 ClassHeritage ,则
a. 如果 ClassHeritage 存在,则返回
true ;否则返回 false 。
3. 如果 ClassHeritage 存在,则
a. 如果 ClassHeritage Contains
symbol 是 true ,则返回 true 。
4. 返回 ComputedPropertyContains
的结果,其参数为 symbol ,在 ClassBody 中。
Note 2
Static semantic rules that depend upon substructure generally do not look into class bodies except
for
PropertyName s.
ClassStaticBlock
:
static
{
ClassStaticBlockBody
}
1. 返回 false 。
Note 3
依赖子结构的静态语义规则通常不会检查static
初始化块。
ArrowFunction
:
ArrowParameters
=>
ConciseBody
1. 如果 symbol 不是 NewTarget 、SuperProperty 、SuperCall 、super
或
this
之一,则返回 false 。
2. 如果 ArrowParameters Contains
symbol 为 true ,则返回 true 。
3. 返回 ConciseBody Contains
symbol 。
ArrowParameters
: CoverParenthesizedExpressionAndArrowParameterList
1. 让 formals 为 ArrowFormalParameters ,该
CoverParenthesizedExpressionAndArrowParameterList
被 覆盖 。
2. 返回 formals Contains
symbol 的结果。
AsyncArrowFunction
:
async
AsyncArrowBindingIdentifier
=>
AsyncConciseBody
1. 如果 symbol 不是以下之一:NewTarget ,SuperProperty ,SuperCall ,super
,或
this
,返回 false 。
2. 返回 AsyncConciseBody 的 Contains
symbol 的结果。
AsyncArrowFunction
:
CoverCallExpressionAndAsyncArrowHead
=>
AsyncConciseBody
1. 如果 symbol 不是以下之一:NewTarget ,SuperProperty ,SuperCall ,super
,或
this
,返回 false 。
2. 令 head 为 AsyncArrowHead ,它被 CoverCallExpressionAndAsyncArrowHead
覆盖 。
3. 如果 head Contains
symbol 的结果为 true ,返回 true 。
4. 返回 AsyncConciseBody Contains
symbol 的结果。
Note 4
Contains is used to detect new.target
, this
, and super
usage
within an ArrowFunction or AsyncArrowFunction .
PropertyDefinition
: MethodDefinition
1. 如果 symbol 是 MethodDefinition ,返回
true 。
2. 返回 MethodDefinition ComputedPropertyContains
symbol 的结果。
LiteralPropertyName
: IdentifierName
1. 返回 false 。
MemberExpression
:
MemberExpression
.
IdentifierName
1. 如果 MemberExpression Contains
symbol 是 true ,返回 true 。
2. 返回 false 。
SuperProperty
:
super
.
IdentifierName
1. 如果 symbol 是 ReservedWord super
,返回
true 。
2. 返回 false 。
CallExpression
:
CallExpression
.
IdentifierName
1. 如果 CallExpression Contains
symbol 是 true ,返回 true 。
2. 返回 false 。
OptionalChain
:
?.
IdentifierName
1. 返回 false 。
OptionalChain
:
OptionalChain
.
IdentifierName
1. 如果 OptionalChain Contains
symbol 是 true ,返回 true 。
2. 返回 false 。
8.5.2 静态语义:ComputedPropertyContains
语法定向操作
ComputedPropertyContains 接受参数 symbol (一个语法符号)并返回一个布尔值。它通过以下生成式逐步定义:
ClassElementName
: PrivateIdentifier
PropertyName
: LiteralPropertyName
1. 返回 false 。
PropertyName
:
ComputedPropertyName
1. 返回 ComputedPropertyName 的结果,其中
symbol 被作为 Contains 的参数。
MethodDefinition
:
ClassElementName
(
UniqueFormalParameters
)
{
FunctionBody
}
get
ClassElementName
(
)
{
FunctionBody
}
set
ClassElementName
(
PropertySetParameterList
)
{
FunctionBody
}
1. 返回 ComputedPropertyContains
的结果,其中 ClassElementName 被作为参数
symbol 。
GeneratorMethod
:
*
ClassElementName
(
UniqueFormalParameters
)
{
GeneratorBody
}
1. 返回 ComputedPropertyContains
的结果,其中 ClassElementName 被作为参数
symbol 。
AsyncGeneratorMethod
:
async
*
ClassElementName
(
UniqueFormalParameters
)
{
AsyncGeneratorBody
}
1. 返回 ComputedPropertyContains
的结果,其中 ClassElementName 被作为参数
symbol 。
ClassElementList
:
ClassElementList
ClassElement
1. 令 inList 为 ComputedPropertyContains
的结果,其中 ClassElementList 被作为参数
symbol 。
2. 如果 inList 为 true ,则返回
true 。
3. 返回 ComputedPropertyContains
的结果,其中 ClassElement 被作为参数
symbol 。
ClassElement
:
ClassStaticBlock
1. 返回 false 。
ClassElement
:
;
1. 返回 false 。
AsyncMethod
:
async
ClassElementName
(
UniqueFormalParameters
)
{
AsyncFunctionBody
}
1. 返回 ComputedPropertyContains
的结果,其中 ClassElementName 被作为参数
symbol 。
FieldDefinition
:
ClassElementName
Initializer opt
1. 返回 ComputedPropertyContains
的结果,其中 ClassElementName 被作为参数
symbol 。
8.6 杂项
这些操作在整个规范的多个地方使用。
8.6.1 运行时语义: InstantiateFunctionObject
语法导向操作
InstantiateFunctionObject 接受参数 env (一个 环境记录 )和 privateEnv (一个
私有环境记录 或
null )并返回一个 ECMAScript 函数对象 。它按以下生成规则定义:
FunctionDeclaration
:
function
BindingIdentifier
(
FormalParameters
)
{
FunctionBody
}
function
(
FormalParameters
)
{
FunctionBody
}
1. 返回 InstantiateOrdinaryFunctionObject
对 FunctionDeclaration 的调用,参数为
env 和 privateEnv 。
GeneratorDeclaration
:
function
*
BindingIdentifier
(
FormalParameters
)
{
GeneratorBody
}
function
*
(
FormalParameters
)
{
GeneratorBody
}
1. 返回 InstantiateGeneratorFunctionObject
对 GeneratorDeclaration 的调用,参数为
env 和 privateEnv 。
AsyncGeneratorDeclaration
:
async
function
*
BindingIdentifier
(
FormalParameters
)
{
AsyncGeneratorBody
}
async
function
*
(
FormalParameters
)
{
AsyncGeneratorBody
}
1. 返回 InstantiateAsyncGeneratorFunctionObject
对 AsyncGeneratorDeclaration
的调用,参数为 env 和 privateEnv 。
AsyncFunctionDeclaration
:
async
function
BindingIdentifier
(
FormalParameters
)
{
AsyncFunctionBody
}
async
function
(
FormalParameters
)
{
AsyncFunctionBody
}
1. 返回 InstantiateAsyncFunctionObject
对 AsyncFunctionDeclaration
的调用,参数为 env 和 privateEnv 。
8.6.2 运行时语义:绑定初始化
语法导向操作
BindingInitialization 接受参数 value (一个ECMAScript
语言值 )和 environment (一个环境记录 或
undefined )并返回一个包含
unused 的正常完成或一个突然完成 。
注
undefined 被传递给 environment 以表明应该使用PutValue 操作来分配初始化值。对于var
语句和一些非严格函数 的形式参数列表(参见10.2.11 )来说就是这种情况。在这些情况下,词法绑定在其初始化器评估之前被提升和预初始化。
它在以下生成式中逐段定义:
BindingIdentifier
: Identifier
1. 让 name 成为 StringValue 的
Identifier 。
2. 返回 ? InitializeBoundName (name , value ,
environment )。
BindingIdentifier
: yield
1. 返回 ? InitializeBoundName ("yield" , value ,
environment )。
BindingIdentifier
:
await
1. 返回 ? InitializeBoundName ("await" , value ,
environment )。
BindingPattern
:
ObjectBindingPattern
1. 执行 ? RequireObjectCoercible (value )。
2. 返回 ? BindingInitialization of ObjectBindingPattern with
arguments value 和 environment 。
BindingPattern
:
ArrayBindingPattern
1. 让 iteratorRecord 为 ? GetIterator (value , sync )。
2. 让 result 为 Completion (IteratorBindingInitialization of ArrayBindingPattern with
arguments iteratorRecord 和 environment )。
3. 如果 iteratorRecord .[[Done]] 为
false ,返回 ? IteratorClose (iteratorRecord , result )。
4. 返回 ? result 。
ObjectBindingPattern
:
{
}
1. 返回 unused 。
ObjectBindingPattern
:
{
BindingPropertyList
}
{
BindingPropertyList
,
}
1. 执行 ? PropertyBindingInitialization of BindingPropertyList with
arguments value 和 environment 。
2. 返回 unused 。
ObjectBindingPattern
:
{
BindingRestProperty
}
1. 让 excludedNames 成为一个新的空列表 。
2. 返回 ? RestBindingInitialization of BindingRestProperty with
arguments value , environment , 和 excludedNames 。
ObjectBindingPattern
:
{
BindingPropertyList
,
BindingRestProperty
}
1. 让 excludedNames 成为 ? PropertyBindingInitialization of BindingPropertyList with
arguments value 和 environment 。
2. 返回 ? RestBindingInitialization of BindingRestProperty with
arguments value , environment , 和 excludedNames 。
8.6.2.1 InitializeBoundName ( name , value ,
environment )
抽象操作 InitializeBoundName 接受参数 name (字符串),value (一个 ECMAScript 语言值 ),和
environment (一个 环境记录 或
undefined )并返回一个 正常完成记录 包含
unused 或者一个 异常完成 。它在调用时执行以下步骤:
1. 如果 environment 不是 undefined ,那么
a. 执行
! environment .InitializeBinding(name , value )。
b. 返回 unused 。
2. 否则,
a. 让 lhs 等于 ? ResolveBinding (name )。
b. 返回 ? PutValue (lhs , value )。
8.6.3 运行时语义:IteratorBindingInitialization
语法指引操作
IteratorBindingInitialization 接受参数 iteratorRecord (一个 迭代器记录 )和
environment (一个 环境记录 或
undefined )并返回一个 正常完成记录 (包含
unused )或者一个 异常完成记录 。
注
当 environment 被传递为 undefined 时,表示应该使用 PutValue
操作来分配初始化值。这种情况出现在 非严格函数
的形式参数列表中。在这种情况下,形式参数绑定会被预初始化,以处理具有相同名称的多个参数的可能性。
它通过以下生成式逐段定义:
ArrayBindingPattern
:
[
]
1. 返回 unused 。
ArrayBindingPattern
:
[
Elision
]
1. 返回 ? IteratorDestructuringAssignmentEvaluation of Elision with argument
iteratorRecord 。
ArrayBindingPattern
:
[
Elision opt
BindingRestElement
]
1. 如果 Elision 存在,那么
a. 执行 ? IteratorDestructuringAssignmentEvaluation of Elision with
argument iteratorRecord 。
2. 返回 ? IteratorBindingInitialization of BindingRestElement with
arguments iteratorRecord 和 environment 。
ArrayBindingPattern
:
[
BindingElementList
,
Elision
]
1. 执行 ? IteratorBindingInitialization of BindingElementList with
arguments iteratorRecord 和 environment 。
2. 返回 ? IteratorDestructuringAssignmentEvaluation of Elision with argument
iteratorRecord 。
ArrayBindingPattern
:
[
BindingElementList
,
Elision opt
BindingRestElement
]
1. 执行 ? IteratorBindingInitialization of BindingElementList with
arguments iteratorRecord 和 environment 。
2. 如果 Elision 存在,那么
a. 执行 ? IteratorDestructuringAssignmentEvaluation of Elision with
argument iteratorRecord 。
3. 返回 ? IteratorBindingInitialization of BindingRestElement with
arguments iteratorRecord 和 environment 。
BindingElementList
:
BindingElementList
,
BindingElisionElement
1. 执行 ? IteratorBindingInitialization of BindingElementList with
arguments iteratorRecord 和 environment 。
2. 返回 ? IteratorBindingInitialization of BindingElisionElement with
arguments iteratorRecord 和 environment 。
BindingElisionElement
:
Elision
BindingElement
1. 执行 ? IteratorDestructuringAssignmentEvaluation of Elision with argument
iteratorRecord 。
2. 返回 ? IteratorBindingInitialization of BindingElement with arguments
iteratorRecord 和 environment 。
单名称绑定(SingleNameBinding)
:
绑定标识符(BindingIdentifier)
初始化器(Initializer)
opt
1. 设 bindingId 为
字符串值(StringValue)
的
绑定标识符(BindingIdentifier)
。
2. 设 lhs 为
?
解析绑定(ResolveBinding)
(bindingId , environment )。
3. 设 v 为 未定义(undefined) 。
4. 如果 iteratorRecord 的 [[完成]]([[Done]]) 为 false ,则:
a. 设 next 为
?
迭代器步骤值(IteratorStepValue)
(iteratorRecord )。
b. 如果 next 不是 完成(done) ,则:
i. 将 v 设为 next 。
5. 如果存在
初始化器(Initializer)
且 v 为 未定义(undefined) ,则:
a. 如果
是否匿名函数定义(IsAnonymousFunctionDefinition)
(
初始化器(Initializer)
) 为 true ,则:
i. 将 v 设为
?
命名评估(NamedEvaluation)
(
初始化器(Initializer)
,参数为 bindingId )。
b. 否则:
i. 设 defaultValue 为
?
评估(Evaluation)
(
初始化器(Initializer)
)。
ii. 将 v 设为
?
获取值(GetValue)
(defaultValue )。
6. 如果 environment 为 未定义(undefined) ,
则返回 ?
放置值(PutValue)
(lhs ,v )。
7. 返回
?
初始化引用绑定(InitializeReferencedBinding)
(lhs ,v )。
绑定元素(BindingElement)
:
绑定模式(BindingPattern)
初始化器(Initializer)
opt
1. 设 v 为 未定义(undefined) 。
2. 如果 iteratorRecord 的 [[完成]]([[Done]]) 为 false ,则:
a. 设 next 为
?
迭代器步骤值(IteratorStepValue)
(iteratorRecord )。
b. 如果 next 不是 完成(done) ,则:
i. 将 v 设为 next 。
3. 如果存在
初始化器(Initializer)
且 v 为 未定义(undefined) ,则:
a. 设 defaultValue 为
?
评估(Evaluation)
(
初始化器(Initializer)
)。
b. 将 v 设为
?
获取值(GetValue)
(defaultValue )。
4. 返回 ?
绑定初始化(BindingInitialization)
的
绑定模式(BindingPattern)
,参数为 v 和 environment 。
BindingRestElement
:
...
BindingIdentifier
1. 设 lhs 为 ?
ResolveBinding
(
StringValue
的
BindingIdentifier
, environment )。
2. 设 A 为 !
ArrayCreate
(0)。
3. 设 n 为 0。
4. 重复,
a. 设 next 为 done 。
b. 如果 iteratorRecord 的 [[Done]] 为 false ,则:
i. 将 next 设为 ?
IteratorStepValue
(iteratorRecord )。
c. 如果 next 为 done ,则:
i. 如果 environment 为
undefined ,则返回 ?
PutValue
(lhs , A )。
ii. 返回 ?
InitializeReferencedBinding
(lhs , A )。
d. 执行 !
CreateDataPropertyOrThrow
(A , !
ToString
(
𝔽
(n )), next )。
e. 将 n 设为 n + 1。
BindingRestElement
:
...
BindingPattern
1. 设 A 为 !
ArrayCreate
(0)。
2. 设 n 为 0。
3. 重复,
a. 设 next 为 done 。
b. 如果 iteratorRecord 的 [[Done]] 为 false ,则:
i. 将 next 设为 ?
IteratorStepValue
(iteratorRecord )。
c. 如果 next 为 done ,则:
i. 返回 ?
BindingInitialization
of
BindingPattern
,参数为 A 和 environment 。
d. 执行 !
CreateDataPropertyOrThrow
(A , !
ToString
(
𝔽
(n )), next )。
e. 将 n 设为 n + 1。
FormalParameters
:
[empty]
1. 返回 unused 。
FormalParameters
:
FormalParameterList
,
FunctionRestParameter
1. 执行 ?
IteratorBindingInitialization
of
FormalParameterList
,参数为 iteratorRecord 和 environment 。
2. 返回 ?
IteratorBindingInitialization
of
FunctionRestParameter
,参数为 iteratorRecord 和 environment 。
FormalParameterList
:
FormalParameterList
,
FormalParameter
1. 执行 ?
IteratorBindingInitialization
of
FormalParameterList
,参数为 iteratorRecord 和 environment 。
2. 返回 ?
IteratorBindingInitialization
of
FormalParameter
,参数为 iteratorRecord 和 environment 。
ArrowParameters
:
BindingIdentifier
1. 令 v 为 undefined 。
2.
断言
:iteratorRecord .[[Done]] 为 false 。
3. 令 next 为 ?
IteratorStepValue
(iteratorRecord )。
4. 如果 next 不是 done ,则
a. 将 v 设置为 next 。
5. 返回 ?
BindingInitialization
of
BindingIdentifier
,参数为 v 和 environment 。
ArrowParameters
:
CoverParenthesizedExpressionAndArrowParameterList
1. 令 formals 为 ArrowFormalParameters
,它被 CoverParenthesizedExpressionAndArrowParameterList
所覆盖。
2. 返回 ?
IteratorBindingInitialization
of formals ,参数为 iteratorRecord 和 environment 。
AsyncArrowBindingIdentifier
:
BindingIdentifier
1. 令 v 为 undefined 。
2.
断言
:iteratorRecord .[[Done]] 为 false 。
3. 令 next 为 ?
IteratorStepValue
(iteratorRecord )。
4. 如果 next 不是 done ,则
a. 将 v 设置为 next 。
5. 返回 ?
BindingInitialization
of
BindingIdentifier
,参数为 v 和 environment 。
8.6.4 静态语义: AssignmentTargetType
语法导向操作 AssignmentTargetType
不接受参数,返回 simple 或 invalid 。它在以下各个产生式上被分段定义:
IdentifierReference
: Identifier
1. 如果这个 IdentifierReference 包含在
严格模式代码 中,并且 Identifier 的
StringValue 是
"eval" 或 "arguments" ,则返回 invalid 。
2. 返回 simple 。
IdentifierReference
:
yield
await
CallExpression
:
CallExpression
[
Expression
]
CallExpression
.
IdentifierName
CallExpression
.
PrivateIdentifier
MemberExpression
:
MemberExpression
[
Expression
]
MemberExpression
.
IdentifierName
SuperProperty
MemberExpression
.
PrivateIdentifier
1. 返回 simple 。
PrimaryExpression
:
CoverParenthesizedExpressionAndArrowParameterList
1. 设 expr 是由 ParenthesizedExpression 所
包含 的部分。
2. 返回 AssignmentTargetType
的 expr 。
PrimaryExpression
:
this
Literal
ArrayLiteral
ObjectLiteral
FunctionExpression
ClassExpression
GeneratorExpression
AsyncFunctionExpression
AsyncGeneratorExpression
RegularExpressionLiteral
TemplateLiteral
CallExpression
:
CoverCallExpressionAndAsyncArrowHead
SuperCall
ImportCall
CallExpression
Arguments
CallExpression
TemplateLiteral
NewExpression
:
new
NewExpression
MemberExpression
:
MemberExpression
TemplateLiteral
new
MemberExpression
Arguments
NewTarget :
new
.
target
ImportMeta
:
import
.
meta
LeftHandSideExpression
:
OptionalExpression
UpdateExpression
:
LeftHandSideExpression
++
LeftHandSideExpression
--
++
UnaryExpression
--
UnaryExpression
UnaryExpression
:
delete
UnaryExpression
void
UnaryExpression
typeof
UnaryExpression
+
UnaryExpression
-
UnaryExpression
~
UnaryExpression
!
UnaryExpression
AwaitExpression
ExponentiationExpression
:
UpdateExpression
**
ExponentiationExpression
MultiplicativeExpression
:
MultiplicativeExpression
MultiplicativeOperator
ExponentiationExpression
AdditiveExpression
:
AdditiveExpression
+
MultiplicativeExpression
AdditiveExpression
-
MultiplicativeExpression
ShiftExpression
:
ShiftExpression
<<
AdditiveExpression
ShiftExpression
>>
AdditiveExpression
ShiftExpression
>>>
AdditiveExpression
RelationalExpression
:
RelationalExpression
<
ShiftExpression
RelationalExpression
>
ShiftExpression
RelationalExpression
<=
ShiftExpression
RelationalExpression
>=
ShiftExpression
RelationalExpression
instanceof
ShiftExpression
RelationalExpression
in
ShiftExpression
PrivateIdentifier
in
ShiftExpression
EqualityExpression
:
EqualityExpression
==
RelationalExpression
EqualityExpression
!=
RelationalExpression
EqualityExpression
===
RelationalExpression
EqualityExpression
!==
RelationalExpression
BitwiseANDExpression
:
BitwiseANDExpression
&
EqualityExpression
BitwiseXORExpression
:
BitwiseXORExpression
^
BitwiseANDExpression
BitwiseORExpression
:
BitwiseORExpression
|
BitwiseXORExpression
LogicalANDExpression
:
LogicalANDExpression
&&
BitwiseORExpression
LogicalORExpression
:
LogicalORExpression
||
LogicalANDExpression
CoalesceExpression
:
CoalesceExpressionHead
??
BitwiseORExpression
ConditionalExpression
:
ShortCircuitExpression
?
AssignmentExpression
:
AssignmentExpression
AssignmentExpression
:
YieldExpression
ArrowFunction
AsyncArrowFunction
LeftHandSideExpression
=
AssignmentExpression
LeftHandSideExpression
AssignmentOperator
AssignmentExpression
LeftHandSideExpression
&&=
AssignmentExpression
LeftHandSideExpression
||=
AssignmentExpression
LeftHandSideExpression
??=
AssignmentExpression
Expression
:
Expression
,
AssignmentExpression
1. 返回 invalid 。
8.6.5 静态语义:PropName
语法导向操作
PropName 不接受任何参数,并返回一个字符串或 empty 。它在以下生成式上逐步定义:
PropertyDefinition
: IdentifierReference
1. 返回 StringValue 的
IdentifierReference 。
PropertyDefinition
:
...
AssignmentExpression
1. 返回 empty .
PropertyDefinition
:
PropertyName
:
AssignmentExpression
1. 返回 PropName 的 PropertyName 。
LiteralPropertyName
: IdentifierName
1. 返回 StringValue
的 IdentifierName 。
LiteralPropertyName
:
StringLiteral
1. 返回 SV
的 StringLiteral 。
LiteralPropertyName
:
NumericLiteral
1. 让 nbr 为 NumericValue
的 NumericLiteral 。
2. 返回 ! ToString (nbr )。
ComputedPropertyName
:
[
AssignmentExpression
]
1. 返回 empty 。
MethodDefinition
:
ClassElementName
(
UniqueFormalParameters
)
{
FunctionBody
}
get
ClassElementName
(
)
{
FunctionBody
}
set
ClassElementName
(
PropertySetParameterList
)
{
FunctionBody
}
1. 返回 PropName
的 ClassElementName 。
GeneratorMethod
:
*
ClassElementName
(
UniqueFormalParameters
)
{
GeneratorBody
}
1. 返回 PropName
的 ClassElementName 。
AsyncGeneratorMethod
:
async
*
ClassElementName
(
UniqueFormalParameters
)
{
AsyncGeneratorBody
}
1. 返回 PropName
的 ClassElementName 。
ClassElement
: ClassStaticBlock
1. 返回 empty .
ClassElement
: ;
1. 返回 empty .
AsyncMethod
:
async
ClassElementName
(
UniqueFormalParameters
)
{
AsyncFunctionBody
}
1. 返回 PropName
的 ClassElementName 。
FieldDefinition
:
ClassElementName
Initializer opt
1. 返回 PropName
的 ClassElementName 。
ClassElementName
:
PrivateIdentifier
1. 返回 empty 。
9 可执行代码和执行上下文
9.1 环境记录
环境记录 是一种规范类型,用于根据 ECMAScript 代码的词法嵌套结构,定义标识符 与特定变量和函数的关联。通常,环境记录与
ECMAScript 代码的某些特定语法结构相关联,如函数声明 、块语句 或捕获 子句等。每次评估此类代码时,都会创建一个新的环境记录来记录该代码创建的标识符绑定。
每个环境记录都有一个[[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 异常。如果绑定存在但未初始化,则无论S 的值如何,都会抛出ReferenceError 。
DeleteBinding(N)
从环境记录 中删除一个绑定。字符串值N 是绑定名的文本。如果存在N 的绑定,则移除绑定并返回true 。如果绑定存在但无法移除,则返回false 。如果绑定不存在,则返回true 。
HasThisBinding()
确定环境记录 是否建立了this
绑定。如果建立了,返回true ,否则返回false 。
HasSuperBinding()
确定环境记录 是否建立了super
方法绑定。如果建立了,返回true ,否则返回false 。
WithBaseObject()
如果此环境记录 与with
语句关联,则返回
with 对象。否则,返回undefined 。
9.1.1.1 声明式环境记录
每个声明式环境记录 都与包含变量、常量、let、class、模块、import和/或函数声明的 ECMAScript
程序范围相关联。声明式环境记录绑定其范围内包含的声明所定义的一组标识符。
声明式环境记录的具体规范方法的行为由以下算法定义。
9.1.1.1.1 HasBinding ( N )
声明式环境记录
envRec 的 HasBinding 具体方法接受参数N (一个字符串)并返回一个包含 布尔值的正常完成记录。它确定参数标识符是否是记录绑定的标识符之一。调用时执行以下步骤:
1. 如果envRec 有N 的绑定,则返回true 。
2. 返回false 。
9.1.1.1.2 CreateMutableBinding ( N , D )
声明式环境记录
envRec 的 CreateMutableBinding 具体方法接受参数N (一个字符串)和D (一个布尔值),并返回一个包含
unused 的正常完成记录。它为名称N 创建一个新的未初始化的可变绑定。环境记录 中不应已有N 的绑定。如果D 是true ,则新绑定被标记为可以删除。调用时执行以下步骤:
1. 断言 :envRec 中不存在N 的绑定。
2.
在envRec 中为N 创建一个可变绑定,并记录它未初始化。如果D 是true ,则记录新创建的绑定可以通过后续的
DeleteBinding 调用删除。
3. 返回unused 。
9.1.1.1.3 CreateImmutableBinding ( N , S )
声明式环境记录
envRec 的 CreateImmutableBinding 具体方法接受参数N (一个字符串)和S (一个布尔值),并返回一个包含
unused 的正常完成记录。它为名称N 创建一个新的未初始化的不可变绑定。环境记录 中不应已有N 的绑定。如果S 是true ,则新绑定被标记为严格绑定。调用时执行以下步骤:
1. 断言 :envRec 中不存在N 的绑定。
2.
在envRec 中为N 创建一个不可变绑定,并记录它未初始化。如果S 是true ,则记录新创建的绑定是严格绑定。
3. 返回unused 。
9.1.1.1.4 InitializeBinding ( N , V )
声明式环境记录
envRec 的 InitializeBinding 具体方法接受参数N (一个字符串)和V (一个ECMAScript
语言值 ),并返回一个包含
unused 的正常完成记录。它用于将名称为N 的标识符的当前绑定值设置为V 。必须已存在N 的未初始化绑定。调用时执行以下步骤:
1. 断言 :envRec 中必须有N 的未初始化绑定。
2. 将envRec 中N 的绑定值设置为V 。
3. 记录envRec 中N 的绑定已被初始化。
4. 返回unused 。
9.1.1.1.5 SetMutableBinding ( N , V , S )
声明式环境记录
envRec 的 SetMutableBinding 具体方法接受参数N (一个字符串)、V (一个ECMAScript
语言值 )和S (一个布尔值),并返回一个包含
unused 的正常完成记录或一个抛出完成记录 。它尝试将名称为N 的标识符的当前绑定值更改为V 。通常情况下,已经存在N 的绑定,但在极少数情况下可能不存在。如果绑定是不可变绑定,则如果S 是true ,会抛出TypeError 。调用时执行以下步骤:
1.
如果envRec 中没有N 的绑定,则
a.
如果S 是true ,抛出ReferenceError 异常。
b. 执行
! envRec .CreateMutableBinding(N , true )。
c. 执行 ! envRec .InitializeBinding(N ,
V )。
d. 返回unused 。
2.
如果envRec 中N 的绑定是严格绑定,则将S 设置为true 。
3. 如果envRec 中N 的绑定尚未初始化,则
a. 抛出ReferenceError 异常。
4. 否则,如果envRec 中N 的绑定是可变绑定,则
a. 将其绑定值更改为V 。
5. 否则,
a. 断言 :这是尝试更改不可变绑定的值。
b.
如果S 是true ,抛出TypeError 异常。
6. 返回unused 。
注
在步骤1 中缺少绑定的
ECMAScript 代码示例是:
function f ( ) { eval ("var x; x = (delete x, 0);" ); }
9.1.1.1.6 GetBindingValue ( N , S )
声明式环境记录
envRec 的 GetBindingValue 具体方法接受参数N (一个字符串)和S (一个布尔值),并返回一个包含 一个ECMAScript
语言值 的正常完成记录或一个抛出完成记录 。它返回其绑定标识符的值,其名称为N 。如果绑定存在但未初始化,则抛出ReferenceError ,无论S 的值如何。调用时执行以下步骤:
1. 断言 :envRec 有N 的绑定。
2.
如果envRec 中N 的绑定是未初始化绑定,则抛出ReferenceError 异常。
3. 返回当前绑定到envRec 中N 的值。
9.1.1.1.7 DeleteBinding ( N )
声明式环境记录
envRec 的 DeleteBinding 具体方法接受参数N (一个字符串),并返回一个包含 布尔值的正常完成记录。它只能删除已明确指定为可删除的绑定。调用时执行以下步骤:
1. 断言 :envRec 有N 的绑定。
2.
如果envRec 中N 的绑定不能被删除,则返回false 。
3. 从envRec 中移除N 的绑定。
4. 返回true 。
9.1.1.1.8 HasThisBinding ( )
声明式环境记录
envRec 的 HasThisBinding 具体方法不接受任何参数并返回false 。调用时执行以下步骤:
1. 返回false 。
注
常规声明式环境记录 (即,不是函数环境记录 或模块环境记录 )不提供this
绑定。
9.1.1.1.9 HasSuperBinding ( )
声明式环境记录
envRec 的 HasSuperBinding 具体方法不接受任何参数并返回false 。调用时执行以下步骤:
1. 返回false 。
注
常规声明式环境记录 (即,不是函数环境记录 或模块环境记录 )不提供super
绑定。
9.1.1.1.10 WithBaseObject ( )
声明式环境记录
envRec 的 WithBaseObject 具体方法不接受任何参数并返回undefined 。调用时执行以下步骤:
1. 返回undefined 。
9.1.1.2 对象环境记录
每个对象环境记录 都与一个称为绑定对象 的对象相关联。对象环境记录绑定一组字符串标识符名称,这些名称直接对应于其绑定对象的属性名称。属性键 不是标识符名称 形式的字符串不包括在绑定标识符的集合中。无论其[[Enumerable]] 属性的设置如何,自己的和继承的属性都包括在集合中。由于可以动态添加和删除属性,对象环境记录绑定的标识符集可能会因添加或删除属性的任何操作而改变。作为此类副作用创建的任何绑定都被视为可变绑定,即使相应属性的[[Writable]] 属性为false 。不可变绑定不存在于对象环境记录中。
为with
语句创建的对象环境记录(14.11 )可以将其绑定对象作为隐式this 值用于函数调用。此功能由布尔值[[IsWithEnvironment]] 字段控制。
对象环境记录具有表17 中列出的附加状态字段。
表17: 对象环境记录 的附加字段
字段名称
值
含义
[[BindingObject]]
一个对象
此环境记录 的绑定对象。
[[IsWithEnvironment]]
一个布尔值
指示此环境记录 是否为with
语句创建。
对象环境记录的具体规范方法的行为由以下算法定义。
9.1.1.2.1 HasBinding ( N )
对象环境记录
envRec 的 HasBinding 具体方法接受参数N (一个字符串),并返回一个包含 布尔值的正常完成记录或一个抛出完成记录 。它确定其关联的绑定对象是否具有名称为N 的属性。调用时执行以下步骤:
1. 让bindingObject 成为envRec 的[[BindingObject]] 。
2. 让foundBinding 为? HasProperty (bindingObject , N )。
3.
如果foundBinding 为false ,返回false 。
4. 如果envRec 的[[IsWithEnvironment]] 为false ,返回true 。
5. 让unscopables 为? Get (bindingObject , @@unscopables )。
6. 如果unscopables 是一个对象 ,则
a. 让blocked 为ToBoolean (?
Get (unscopables , N ))。
b.
如果blocked 为true ,返回false 。
7. 返回true 。
9.1.1.2.2 CreateMutableBinding ( N , D )
对象环境记录
envRec 的 CreateMutableBinding 具体方法接受参数N (一个字符串)和D (一个布尔值),并返回一个包含
unused 的正常完成记录或一个抛出完成记录 。它在环境记录 的关联绑定对象中创建一个名为N 的属性,并将其初始化为undefined 。如果D 为true ,新属性的[[Configurable]] 属性设置为true ;否则设置为false 。调用时执行以下步骤:
1. 让bindingObject 成为envRec 的[[BindingObject]] 。
2. 执行? DefinePropertyOrThrow (bindingObject , N ,
PropertyDescriptor { [[Value]] : undefined , [[Writable]] : true , [[Enumerable]] : true , [[Configurable]] : D })。
3. 返回unused 。
注
通常情况下,envRec 不会有N 的绑定,但如果有,DefinePropertyOrThrow 的语义可能会导致替换或遮蔽现有绑定,或返回突然完成 。
9.1.1.2.3 CreateImmutableBinding ( N , S )
对象环境记录 中从未使用过此规范。
9.1.1.2.4 InitializeBinding ( N , V )
对象环境记录
envRec 的 InitializeBinding 具体方法接受参数N (一个字符串)和V (一个ECMAScript
语言值 ),并返回一个包含
unused 的正常完成记录或一个抛出完成记录 。它用于将名称为N 的标识符的当前绑定值设置为V 。调用时执行以下步骤:
1. 执行? envRec .SetMutableBinding (N , V ,
false )。
2. 返回unused 。
注
在此规范中,所有对对象环境记录 的
CreateMutableBinding 的使用都紧随其后调用 InitializeBinding 用于相同的名称。因此,此规范未明确跟踪对象环境记录 中的绑定初始化状态。
9.1.1.2.5 SetMutableBinding ( N , V , S )
对象环境记录
envRec 的 SetMutableBinding 具体方法接受参数N (一个字符串)、V (一个ECMAScript
语言值 )和S (一个布尔值),并返回一个包含
unused 的正常完成记录或一个抛出完成记录 。它尝试将环境记录 的关联绑定对象的名称为N 的属性的值设置为V 。通常情况下,该属性已经存在,但如果不存在或当前不可写,则错误处理由S 决定。调用时执行以下步骤:
1. 让bindingObject 成为envRec 的[[BindingObject]] 。
2. 让stillExists 为? HasProperty (bindingObject , N )。
3.
如果stillExists 为false 且S 为true ,抛出ReferenceError 异常。
4. 执行? Set (bindingObject , N , V ,
S )。
5. 返回unused 。
9.1.1.2.6 GetBindingValue ( N , S )
对象环境记录
envRec 的 GetBindingValue 具体方法接受参数N (一个字符串)和S (一个布尔值),并返回一个包含 一个ECMAScript
语言值 的正常完成记录或一个抛出完成记录 。它返回其关联绑定对象的名称为N 的属性的值。该属性应该已经存在,但如果不存在,则结果取决于S 。调用时执行以下步骤:
1. 让bindingObject 成为envRec 的[[BindingObject]] 。
2. 让value 为? HasProperty (bindingObject , N )。
3. 如果value 为false ,则
a.
如果S 为false ,返回undefined ;否则抛出ReferenceError 异常。
4. 返回? Get (bindingObject , N )。
9.1.1.2.7 DeleteBinding ( N )
对象环境记录
envRec 的 DeleteBinding 具体方法接受参数N (一个字符串),并返回一个包含 布尔值的正常完成记录或一个抛出完成记录 。它只能删除[[Configurable]] 属性为true 的环境对象的属性。调用时执行以下步骤:
1. 让bindingObject 成为envRec 的[[BindingObject]] 。
2. 返回? bindingObject .[[Delete]] (N )。
9.1.1.2.8 HasThisBinding ( )
对象环境记录
envRec 的 HasThisBinding 具体方法不接受任何参数并返回false 。调用时执行以下步骤:
1. 返回false 。
注
9.1.1.2.9 HasSuperBinding ( )
对象环境记录
envRec 的 HasSuperBinding 具体方法不接受任何参数并返回false 。调用时执行以下步骤:
1. 返回false 。
注
9.1.1.2.10 WithBaseObject ( )
对象环境记录
envRec 的 WithBaseObject 具体方法不接受任何参数,并返回一个对象或undefined 。调用时执行以下步骤:
1. 如果envRec 的[[IsWithEnvironment]] 为true ,返回envRec 的[[BindingObject]] 。
2. 否则,返回undefined 。
9.1.1.3 函数环境记录
函数环境记录 是一种
声明性环境记录 ,
用于表示函数的顶级作用域,并且如果函数不是一个箭头函数 ,则提供一个
this
绑定。如果函数不是一个箭头函数 函数并引用
super
,则其函数环境记录还包含用于在函数内部执行super
方法调用的状态。
函数环境记录具有表18 中列出的附加状态字段。
表18: 函数环境记录 的附加字段
字段名称
值
含义
[[ThisValue]]
一个ECMAScript语言值
这是该函数调用中使用的this 值。
[[ThisBindingStatus]]
lexical , initialized 或
uninitialized
如果值是lexical ,则这是一个箭头函数 ,并且没有本地的this 值。
[[FunctionObject]]
一个ECMAScript 函数对象
导致创建此环境记录 的函数对象 。
[[NewTarget]]
一个对象或undefined
如果此环境记录 是由[[Construct]] 内部方法创建的,
则[[NewTarget]] 是[[Construct]] 的newTarget 参数的值。
否则,其值为undefined 。
函数环境记录支持声明性环境记录 中列出的所有方法,
并且除了HasThisBinding和HasSuperBinding方法之外,其它所有方法的规范相同。
此外,函数环境记录还支持表19 中列出的方法:
表19: 函数环境记录 的附加方法
方法
目的
BindThisValue(V)
设置[[ThisValue]] 并记录它已被初始化。
GetThisBinding()
返回此环境记录 的this
绑定的值。
如果this
绑定尚未初始化,则抛出ReferenceError 异常。
GetSuperBase()
返回在此环境记录 中绑定的super
属性访问的基础对象。
值undefined 表示这些访问将产生运行时错误。
函数环境记录附加具体方法的行为由以下算法定义:
9.1.1.3.1 BindThisValue ( V )
函数环境记录BindThisValue 具体方法接受参数V (一个ECMAScript语言值 )并返回一个包含ECMAScript语言值 的正常完成记录或一个抛出完成记录 。
调用时执行以下步骤:
1. 断言 : envRec .[[ThisBindingStatus]] 不是lexical 。
2. 如果envRec .[[ThisBindingStatus]] 是initialized ,抛出ReferenceError 异常。
3. 将envRec .[[ThisValue]] 设置为V 。
4. 将envRec .[[ThisBindingStatus]] 设置为initialized 。
5. 返回V 。
9.1.1.3.2 HasThisBinding ( )
函数环境记录HasThisBinding 具体方法不接受任何参数并返回一个布尔值。
调用时执行以下步骤:
1. 如果envRec .[[ThisBindingStatus]] 是lexical ,返回false ;
否则,返回true 。
9.1.1.3.3 HasSuperBinding ( )
函数环境记录HasSuperBinding 具体方法不接受任何参数并返回一个布尔值。
调用时执行以下步骤:
1. 如果envRec .[[ThisBindingStatus]] 是lexical ,返回false 。
2. 如果envRec .[[FunctionObject]] .[[HomeObject]] 是undefined ,返回false ;
否则,返回true 。
9.1.1.3.4 GetThisBinding ( )
函数环境记录GetThisBinding 具体方法不接受任何参数并返回一个包含ECMAScript语言值 的正常完成记录或一个抛出完成记录 。
调用时执行以下步骤:
1. 断言 : envRec .[[ThisBindingStatus]] 不是lexical 。
2. 如果envRec .[[ThisBindingStatus]] 是uninitialized ,抛出ReferenceError 异常。
3. 返回envRec .[[ThisValue]] 。
9.1.1.3.5 GetSuperBase ( )
函数环境记录GetSuperBase 具体方法不接受任何参数并返回一个包含一个对象、null 或undefined 的正常完成记录或一个抛出完成记录 。
调用时执行以下步骤:
1. 让home 成为envRec .[[FunctionObject]] .[[HomeObject]] 。
2.
如果home 是undefined ,返回undefined 。
3. 断言 : home 是一个对象 。
4. 返回? 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
绑定的值。
HasVarDeclaration (N)
确定参数标识符是否在此环境记录 中具有通过变量声明 、
函数声明 、
生成器声明 、
异步函数声明 、
或异步生成器声明 创建的绑定。
HasLexicalDeclaration (N)
确定参数标识符是否在此环境记录 中具有通过词法声明(如词法声明 或类声明 )创建的绑定。
HasRestrictedGlobalProperty (N)
确定参数是否为全局对象 属性的名称,该属性不得被全局词法绑定遮蔽。
CanDeclareGlobalVar (N)
确定是否可以成功调用相应的CreateGlobalVarBinding方法,并为相同的参数N 声明全局变量。
CanDeclareGlobalFunction (N)
确定是否可以成功调用相应的CreateGlobalFunctionBinding方法,并为相同的参数N 声明全局函数。
CreateGlobalVarBinding(N, D)
用于在[[ObjectRecord]] 组件中创建并初始化一个全局var
绑定,
该绑定的初始值为undefined 。绑定将是可变绑定。
相应的全局对象 属性将具有适合var
的属性值。
字符串值N 是绑定的名称。如果D 为true ,则绑定可以被删除。
在逻辑上等同于CreateMutableBinding后跟SetMutableBinding,但它允许对var声明进行特殊处理。
CreateGlobalFunctionBinding(N, V, D)
在[[ObjectRecord]] 组件中创建并初始化一个全局function
绑定。
绑定将是可变绑定。相应的全局对象 属性将具有适合function
的属性值。
字符串值N 是绑定的名称。V 是初始化值。
如果布尔参数D 为true ,则绑定可以被删除。
在逻辑上等同于CreateMutableBinding后跟SetMutableBinding,但它允许对函数声明进行特殊处理。
具体规范方法的行为定义如下算法。
9.1.1.4.1 HasBinding ( N )
全局环境记录envRec 的HasBinding具体方法接受参数N (字符串),返回一个正常完成记录 ,包含一个布尔值或一个抛出完成记录 。它确定参数标识符是否被记录绑定。调用时执行以下步骤:
1. 设DclRec 为envRec 的[[DeclarativeRecord]] 。
2.
如果! DclRec .HasBinding(N )为true ,返回true 。
3. 设ObjRec 为envRec 的[[ObjectRecord]] 。
4. 返回? ObjRec .HasBinding (N )。
9.1.1.4.2 CreateMutableBinding ( N , D )
全局环境记录envRec 的CreateMutableBinding具体方法接受参数N (字符串)和D (布尔值),返回一个正常完成记录 ,包含未使用 或一个抛出完成记录 。它创建一个新的未初始化的可变绑定,绑定在相关的声明记录中。声明记录中不能已经存在N 的绑定。如果D 为true ,新的绑定标记为可删除。调用时执行以下步骤:
1. 设DclRec 为envRec 的[[DeclarativeRecord]] 。
2.
如果! DclRec .HasBinding(N )为true ,抛出类型错误 异常。
3. 返回
! DclRec .CreateMutableBinding(N , D )。
9.1.1.4.3 CreateImmutableBinding ( N , S )
全局环境记录envRec 的CreateImmutableBinding具体方法接受参数N (字符串)和S (布尔值),返回一个正常完成记录 ,包含未使用 或一个抛出完成记录 。它创建一个新的未初始化的不可变绑定。该环境记录 中不能已经存在N 的绑定。如果S 为true ,新的绑定标记为严格绑定。调用时执行以下步骤:
1. 设DclRec 为envRec 的[[DeclarativeRecord]] 。
2.
如果! DclRec .HasBinding(N )为true ,抛出类型错误 异常。
3. 返回
! DclRec .CreateImmutableBinding(N , S )。
9.1.1.4.4 InitializeBinding ( N , V )
全局环境记录envRec 的InitializeBinding具体方法接受参数N (字符串)和V (ECMAScript语言值 ),返回一个正常完成记录 ,包含未使用 或一个抛出完成记录 。它用于将标识符的当前绑定的值设置为V 。必须已经存在一个未初始化的N 绑定。调用时执行以下步骤:
1. 设DclRec 为envRec 的[[DeclarativeRecord]] 。
2.
如果! DclRec .HasBinding(N )为true ,则
a. 返回
! DclRec .InitializeBinding(N , V )。
3. 断言 :如果绑定存在,它必须在对象环境记录 中。
4. 设ObjRec 为envRec 的[[ObjectRecord]] 。
5. 返回? ObjRec .InitializeBinding (N , V )。
9.1.1.4.5 SetMutableBinding ( N , V , S
)
全局环境记录envRec 的SetMutableBinding具体方法接受参数N (字符串)、V (ECMAScript语言值 )和S (布尔值),返回一个正常完成记录 ,包含未使用 或一个抛出完成记录 。它尝试将标识符的当前绑定的值更改为V 。如果绑定是不可变的,并且S 为true ,则抛出类型错误 。通常已经存在名为N 的属性,但如果不存在或当前不可写,错误处理由S 决定。调用时执行以下步骤:
1. 设DclRec 为envRec 的[[DeclarativeRecord]] 。
2.
如果! DclRec .HasBinding(N )为true ,则
a. 返回
? DclRec .SetMutableBinding(N , V , S )。
3. 设ObjRec 为envRec 的[[ObjectRecord]] 。
4. 返回? ObjRec .SetMutableBinding (N , V ,
S )。
9.1.1.4.6 GetBindingValue ( N , S )
全局环境记录envRec 的GetBindingValue具体方法接受参数N (字符串)和S (布尔值),返回一个正常完成记录 ,包含一个ECMAScript语言值 或一个抛出完成记录 。它返回标识符N 的绑定值。如果绑定是未初始化的,则抛出引用错误 异常。通常已经存在名为N 的属性,但如果不存在或当前不可写,错误处理由S 决定。调用时执行以下步骤:
1. 设DclRec 为envRec 的[[DeclarativeRecord]] 。
2.
如果! DclRec .HasBinding(N )为true ,则
a. 返回
? DclRec .GetBindingValue(N , S )。
3. 设ObjRec 为envRec 的[[ObjectRecord]] 。
4. 返回? ObjRec .GetBindingValue (N , S )。
9.1.1.4.7 DeleteBinding ( N )
全局环境记录envRec 的DeleteBinding具体方法接受参数N (字符串),返回一个正常完成记录 ,包含一个布尔值或一个抛出完成记录 。它只能删除已明确指定为可删除的绑定。调用时执行以下步骤:
1. 设DclRec 为envRec 的[[DeclarativeRecord]] 。
2.
如果! DclRec .HasBinding(N )为true ,则
a. 返回
! DclRec .DeleteBinding(N )。
3. 设ObjRec 为envRec 的[[ObjectRecord]] 。
4. 设globalObject 为ObjRec 的[[BindingObject]] 。
5. 设existingProp 为? HasOwnProperty (globalObject , N )。
6. 如果existingProp 为true ,则
a. 设status 为? ObjRec .DeleteBinding (N )。
b.
如果status 为true ,并且envRec 的[[VarNames]] 包含N ,则
i. 从envRec 的[[VarNames]] 中删除N 。
c. 返回status 。
7. 返回true 。
9.1.1.4.8 HasThisBinding ( )
全局环境记录envRec 的HasThisBinding具体方法不接受参数,返回true 。调用时执行以下步骤:
1. 返回true 。
注
9.1.1.4.9 HasSuperBinding ( )
全局环境记录envRec 的HasSuperBinding具体方法不接受参数,返回false 。调用时执行以下步骤:
1. 返回false 。
注
9.1.1.4.10 WithBaseObject ( )
全局环境记录envRec 的WithBaseObject具体方法不接受参数,返回undefined 。调用时执行以下步骤:
1. 返回undefined 。
9.1.1.4.11 GetThisBinding ( )
全局环境记录envRec 的GetThisBinding具体方法不接受参数,返回一个正常完成记录 ,包含一个对象。调用时执行以下步骤:
1. 返回envRec 的[[GlobalThisValue]] 。
9.1.1.4.12 HasVarDeclaration ( N )
全局环境记录envRec 的HasVarDeclaration具体方法接受参数N (字符串),返回一个布尔值。它确定参数标识符是否在此记录中具有通过变量语句 或函数声明 创建的绑定。调用时执行以下步骤:
1. 设varDeclaredNames 为envRec 的[[VarNames]] 。
2. 如果varDeclaredNames 包含N ,返回
true 。
3. 返回false 。
9.1.1.4.13 HasLexicalDeclaration ( N )
全局环境记录envRec 的HasLexicalDeclaration具体方法接受参数N (字符串),返回一个布尔值。它确定参数标识符是否在此记录中具有通过词法声明(如词法声明 或类声明 )创建的绑定。调用时执行以下步骤:
1. 设DclRec 为envRec 的[[DeclarativeRecord]] 。
2. 返回! DclRec .HasBinding(N )。
9.1.1.4.14 HasRestrictedGlobalProperty ( N )
全局环境记录envRec 的HasRestrictedGlobalProperty具体方法接受参数N (字符串),返回一个正常完成记录 ,包含一个布尔值或一个抛出完成记录 。它确定参数标识符是否为全局对象 属性的名称,该属性不得被全局词法绑定遮蔽。调用时执行以下步骤:
1. 设ObjRec 为envRec 的[[ObjectRecord]] 。
2. 设globalObject 为ObjRec 的[[BindingObject]] 。
3. 设existingProp 为? globalObject .[[GetOwnProperty]] (N )。
4. 如果existingProp 为未定义 ,
返回false 。
5. 如果existingProp 的[[Configurable]] 为true ,返回false 。
6. 返回true 。
注
在全局对象 上可能存在直接创建的属性,而不是通过var或函数声明创建的。
不得创建具有与全局对象 的不可配置属性相同名称的全局词法绑定。全局属性"undefined" 就是一个例子。
9.1.1.4.15 CanDeclareGlobalVar ( N )
全局环境记录envRec 的CanDeclareGlobalVar具体方法接受参数N (字符串),返回一个正常完成记录 ,包含一个布尔值或一个抛出完成记录 。它确定是否可以成功调用相应的CreateGlobalVarBinding方法,并为相同的参数N 声明全局变量。允许冗余的var声明和已存在的全局对象 属性的var声明。调用时执行以下步骤:
1. 设ObjRec 为envRec 的[[ObjectRecord]] 。
2. 设globalObject 为ObjRec 的[[BindingObject]] 。
3. 设hasProperty 为? HasOwnProperty (globalObject , N )。
4. 如果hasProperty 为true ,返回
true 。
5. 返回? IsExtensible (globalObject )。
9.1.1.4.16 CanDeclareGlobalFunction ( N )
全局环境记录envRec 的CanDeclareGlobalFunction具体方法接受参数N (字符串),返回一个正常完成记录 ,包含一个布尔值或一个抛出完成记录 。它确定是否可以成功调用相应的CreateGlobalFunctionBinding方法,并为相同的参数N 声明全局函数。调用时执行以下步骤:
1. 设ObjRec 为envRec 的[[ObjectRecord]] 。
2. 设globalObject 为ObjRec 的[[BindingObject]] 。
3. 设existingProp 为? globalObject .[[GetOwnProperty]] (N )。
4. 如果existingProp 为未定义 ,
返回? IsExtensible (globalObject )。
5. 如果existingProp 的[[Configurable]] 为true ,返回true 。
6. 如果IsDataDescriptor (existingProp )
为true ,且existingProp 具有属性值{ [[Writable]] :
true , [[Enumerable]] :
true },返回true 。
7. 返回false 。
9.1.1.4.17 CreateGlobalVarBinding ( N , D )
全局环境记录envRec 的CreateGlobalVarBinding具体方法接受参数N (字符串)和D (布尔值),返回一个正常完成记录 ,包含未使用 或一个抛出完成记录 。它在相关的对象环境记录 中创建并初始化一个可变绑定,并在相关的[[VarNames]] 中记录绑定名称列表 。如果绑定已经存在,它将被重用并假定为已初始化。调用时执行以下步骤:
1. 设ObjRec 为envRec 的[[ObjectRecord]] 。
2. 设globalObject 为ObjRec 的[[BindingObject]] 。
3. 设hasProperty 为? HasOwnProperty (globalObject , N )。
4. 设extensible 为? IsExtensible (globalObject )。
5.
如果hasProperty 为false 并且extensible 为true ,则
a. 执行? ObjRec .CreateMutableBinding (N ,
D )。
b. 执行? ObjRec .InitializeBinding (N ,
未定义 )。
6. 如果envRec 的[[VarNames]]
不包含N ,则
a. 将N 追加到envRec 的[[VarNames]] 中。
7. 返回未使用 。
9.1.1.4.18 CreateGlobalFunctionBinding ( N , V ,
D )
全局环境记录envRec 的CreateGlobalFunctionBinding具体方法接受参数N (字符串)、V (ECMAScript语言值 )和D (布尔值),返回一个正常完成记录 ,包含未使用 或一个抛出完成记录 。它在相关的对象环境记录 中创建并初始化一个可变绑定,并在相关的[[VarNames]] 中记录绑定名称列表 。如果绑定已经存在,它将被替换。调用时执行以下步骤:
1. 设ObjRec 为envRec 的[[ObjectRecord]] 。
2. 设globalObject 为ObjRec 的[[BindingObject]] 。
3. 设existingProp 为? globalObject .[[GetOwnProperty]] (N )。
4.
如果existingProp 为未定义 或existingProp 的[[Configurable]] 为true ,则
a. 设desc 为属性描述符{ [[Value]] :
V , [[Writable]] :
true , [[Enumerable]] : true ,
[[Configurable]] : D }.
5. 否则,
a. 设desc 为属性描述符{ [[Value]] :
V }。
6. 执行? DefinePropertyOrThrow (globalObject ,
N ,
desc )。
7. 执行
? Set (globalObject , N , V ,
false )。
8. 如果envRec 的[[VarNames]]
不包含N ,则
a. 将N 追加到envRec 的[[VarNames]] 中。
9. 返回未使用 。
注
全局函数声明始终表示为全局对象 的自有属性。
如果可能,将重新配置现有的自有属性以具有一组标准的属性值。
第7 步等效于调用InitializeBinding具体方法,如果globalObject 是代理,则会产生相同的代理陷阱调用顺序。
9.1.1.5 模块环境记录
模块环境记录 是一种
声明环境记录 ,用于表示
ECMAScript
模块
的外部作用域。除了常规的可变和不可变绑定外,模块环境记录还提供了不可变的导入绑定,这些绑定提供了对存在于另一个
环境记录 中目标绑定的间接访问。
模块环境记录支持所有在
声明环境记录 中列出的
表 16
的方法,并共享这些方法的相同规范,除了 GetBindingValue、DeleteBinding、HasThisBinding 和 GetThisBinding 外。此外,模块环境记录还支持在
表
22 中列出的方法:
表 22: 模块环境记录的附加方法
方法
目的
CreateImportBinding(N, M, N2)
在一个模块环境记录中创建一个不可变的间接绑定。字符串值 N 是绑定名称的文本。M 是一个 模块记录 ,N2
是存在于 M 的 模块环境记录
中的一个绑定。
GetThisBinding()
返回该环境记录的 this
绑定的值。
模块环境记录的附加具体规范方法的行为由以下算法定义:
9.1.1.5.1 GetBindingValue ( N , S )
模块环境记录的 GetBindingValue 具体方法 envRec 接受参数 N (字符串)和 S (布尔值),返回一个包含
ECMAScript 语言值的正常完成记录或抛出完成记录。它返回其绑定标识符 N 的值。但是,如果绑定是间接绑定,则返回目标绑定的值。如果绑定存在但未初始化,则抛出
ReferenceError 。调用时执行以下步骤:
1. 断言 : S 为
true 。
2. 断言 : envRec 有一个绑定 N 。
3. 如果 N 的绑定是间接绑定,那么:
a. 设 M 和 N2 为创建该 N 绑定时提供的间接值。
b. 设 targetEnv 为 M 的
[[Environment]] 。
c. 如果 targetEnv 为 empty ,则抛出
ReferenceError 。
d. 返回 ? targetEnv .GetBindingValue(N2 ,
true )。
4. 如果 envRec 中 N 的绑定是未初始化的绑定,则抛出
ReferenceError 。
5. 返回当前绑定在 envRec 中的 N 的值。
注
S 将始终为 true ,因为模块始终是严格模式代码。
9.1.1.5.2 DeleteBinding ( N )
模块环境记录的 DeleteBinding 具体方法在本规范中从未使用。
注
模块环境记录仅在严格代码中使用,并且在严格代码中,早期错误 规则防止 delete
操作符应用于将解析为模块环境记录绑定的引用记录。详见13.5.1.1 。
9.1.1.5.3 HasThisBinding ( )
模块环境记录的 HasThisBinding 具体方法 envRec 不接受任何参数并返回 true 。调用时执行以下步骤:
1. 返回 true 。
注
9.1.1.5.4 GetThisBinding ( )
模块环境记录的 GetThisBinding 具体方法 envRec 不接受任何参数并返回 undefined 。调用时执行以下步骤:
1. 返回 undefined 。
9.1.1.5.5 CreateImportBinding ( N , M , N2
)
模块环境记录的 CreateImportBinding 具体方法 envRec 接受参数 N (字符串)、M (模块记录 )和 N2 (字符串),并返回
未使用 。它为名称 N 创建一个新的初始化的不可变间接绑定。在此环境记录中不得已有名称为 N
的绑定。N2 是 M 的模块环境记录中存在的一个绑定的名称。对新绑定值的访问将间接访问目标绑定的绑定值。调用时执行以下步骤:
1. 断言 :
envRec 不得已有名称为 N 的绑定。
2. 断言 : 当
M 的 [[Environment]] 实例化时,它将具有名称为 N2 的直接绑定。
3. 在 envRec 中创建一个不可变的间接绑定,引用 M 和
N2 作为其目标绑定,并记录该绑定已初始化。
4. 返回 未使用 。
9.1.2 环境记录操作
本规范使用以下 抽象操作 来对
环境记录 进行操作:
9.1.2.1 GetIdentifierReference ( env , name ,
strict )
抽象操作 GetIdentifierReference 接受参数 env (一个 环境记录 或
null )、name (字符串)和 strict (布尔值),返回一个包含 引用记录
的正常完成记录或抛出完成记录。调用时执行以下步骤:
1. 如果 env 是 null ,则
a. 返回 引用记录 {
[[Base]] : unresolvable , [[ReferencedName]] : name , [[Strict]] :
strict , [[ThisValue]] : empty }。
2. 设 exists 为 ? env .HasBinding (name )。
3. 如果 exists 为 true ,则
a. 返回 引用记录 {
[[Base]] : env , [[ReferencedName]] :
name , [[Strict]] : strict , [[ThisValue]] : empty }。
4. 否则,
a. 设 outer 为 env .[[OuterEnv]] 。
b. 返回 ? GetIdentifierReference (outer , name ,
strict )。
9.1.2.2 NewDeclarativeEnvironment ( E )
抽象操作 NewDeclarativeEnvironment 接受参数 E (一个 环境记录 或
null ),返回一个 声明环境记录 。调用时执行以下步骤:
1. 设 env 为一个新的 声明环境记录 ,其中不包含任何绑定。
2. 将 env .[[OuterEnv]] 设置为
E 。
3. 返回 env 。
9.1.2.3 NewObjectEnvironment ( O , W , E )
抽象操作 NewObjectEnvironment 接受参数 O (一个对象)、W (布尔值)和 E (一个 环境记录 或
null ),返回一个 对象环境记录 。调用时执行以下步骤:
1. 设 env 为一个新的 对象环境记录 。
2. 将 env .[[BindingObject]] 设置为
O 。
3. 将 env .[[IsWithEnvironment]]
设置为 W 。
4. 将 env .[[OuterEnv]] 设置为
E 。
5. 返回 env 。
9.1.2.4 NewFunctionEnvironment ( F , newTarget )
抽象操作 NewFunctionEnvironment 接受参数 F (一个 ECMAScript 函数对象 )和
newTarget (一个对象或 undefined ),返回一个 函数环境记录 。调用时执行以下步骤:
1. 设 env 为一个新的 函数环境记录 ,其中不包含任何绑定。
2. 将 env .[[FunctionObject]] 设置为
F 。
3. 如果 F .[[ThisMode]] 为
lexical ,将 env .[[ThisBindingStatus]] 设置为
lexical 。
4. 否则,将 env .[[ThisBindingStatus]] 设置为 uninitialized 。
5. 将 env .[[NewTarget]] 设置为
newTarget 。
6. 将 env .[[OuterEnv]] 设置为
F .[[Environment]] 。
7. 返回 env 。
9.1.2.5 NewGlobalEnvironment ( G , thisValue )
抽象操作 NewGlobalEnvironment 接受参数 G (一个对象)和 thisValue (一个对象),返回一个 全局环境记录 。调用时执行以下步骤:
1. 设 objRec 为 NewObjectEnvironment (G ,
false , null )。
2. 设 dclRec 为 NewDeclarativeEnvironment (null )。
3. 设 env 为一个新的 全局环境记录 。
4. 将 env .[[ObjectRecord]] 设置为
objRec 。
5. 将 env .[[GlobalThisValue]] 设置为
thisValue 。
6. 将 env .[[DeclarativeRecord]]
设置为 dclRec 。
7. 将 env .[[VarNames]] 设置为一个新的空
列表 。
8. 将 env .[[OuterEnv]] 设置为
null 。
9. 返回 env 。
9.1.2.6 NewModuleEnvironment ( E )
抽象操作 NewModuleEnvironment 接受参数 E (一个 环境记录 ),返回一个
模块环境记录 。调用时执行以下步骤:
1. 设 env 为一个新的 模块环境记录 ,其中不包含任何绑定。
2. 将 env .[[OuterEnv]] 设置为
E 。
3. 返回 env 。
9.2 私有环境记录
私有环境记录 是一种用于根据
ECMAScript 代码中的
类声明 和
类表达式 的词法嵌套结构跟踪
私有名称 的规范机制。它们类似于但不同于
环境记录 。每个
私有环境记录 都与一个
类声明 或
类表达式
相关联。每次评估这样的类时,都会创建一个新的
私有环境记录 来记录该类声明的
私有名称 。
每个
私有环境记录
都具有
表 23 中定义的字段。
表 23:
私有环境记录 字段
字段名
值类型
含义
[[OuterPrivateEnvironment]]
一个 私有环境记录 或
null
最近的包含类的
私有环境记录 。如果与此
私有环境记录
关联的类不包含在任何其他类中,则为
null 。
[[Names]]
一个 列表 ,包含
私有名称
该类声明的
私有名称 。
9.2.1 私有环境记录操作
本规范使用以下
抽象操作 来对
私有环境记录 进行操作:
9.2.1.1 NewPrivateEnvironment ( outerPrivEnv )
抽象操作 NewPrivateEnvironment 接受参数 outerPrivEnv (一个
私有环境记录 或
null ),返回一个
私有环境记录 。调用时执行以下步骤:
1. 设 names 为一个新的空
列表 。
2. 返回
私有环境记录 {
[[OuterPrivateEnvironment]] : outerPrivEnv , [[Names]] : names }。
9.2.1.2 ResolvePrivateIdentifier ( privEnv , identifier
)
抽象操作 ResolvePrivateIdentifier 接受参数 privEnv (一个
私有环境记录 )和
identifier (字符串),返回一个
私有名称 。调用时执行以下步骤:
1. 设 names 为 privEnv .[[Names]] 。
2. 对于 names 中的每个 私有名称
pn ,
执行以下步骤:
a. 如果 pn .[[Description]] 是
identifier ,则:
i. 返回 pn 。
3. 设 outerPrivEnv 为 privEnv .[[OuterPrivateEnvironment]] 。
4.
断言 :
outerPrivEnv 不为 null 。
5. 返回 ResolvePrivateIdentifier (
outerPrivEnv , identifier )。
9.3 范围(Realms)
在评估之前,所有 ECMAScript 代码都必须与一个 范围 相关联。从概念上讲,一个
范围 由一组内置对象、一个
ECMAScript 全局环境、在该全局环境范围内加载的所有 ECMAScript 代码,以及其他相关状态和资源组成。
本规范中以 范围记录 表示
范围 ,其字段在
表 24 中指定:
表 24:范围记录 字段
字段名称
值
含义
[[AgentSignifier]]
一个 代理标识符
拥有此 范围 的 代理
[[Intrinsics]]
一个 记录 ,其字段名称是内置键,其值是对象
与此 范围 相关联的代码使用的内置值
[[GlobalObject]]
一个对象或 undefined
此 全局对象 对于此
范围
[[GlobalEnv]]
一个 全局环境记录
此 范围 的全局环境
[[TemplateMap]]
一个 列表 ,包含字段
[[Site]] (一个
模板字面量
解析节点 )和 [[Array]] (一个数组)
模板对象在每个 范围 中分别进行规范化,使用其
范围记录 的 [[TemplateMap]] 。每个 [[Site]] 值是一个
解析节点 ,即一个
模板字面量 。关联的 [[Array]] 值是传递给标签函数的相应模板对象。
注 1
一旦
解析节点 变得不可达,对应的
[[Array]] 也会变得不可达,如果实现从
[[TemplateMap]]
列表中删除该对,这将是不可观察的。
[[LoadedModules]]
一个 列表 ,包含字段
[[Specifier]] (一个字符串)和 [[Module]] (一个
模块记录 )
从此 范围 导入的说明符字符串到已解析的
模块记录
的映射。该列表不包含两个具有相同 [[Specifier]] 的不同
记录 。
注 2
正如在
HostLoadImportedModule (
16.2.1.8
注 1 )中所述,
[[LoadedModules]] 在
范围记录 中仅在没有
活动脚本或模块 的上下文中运行
import()
表达式时使用。
[[HostDefined]]
任何(默认值为 undefined )
为 宿主
保留的字段,用于将其他信息与
范围记录 关联。
9.3.1 创建范围(CreateRealm) ( )
抽象操作 CreateRealm 不接受任何参数并返回一个 范围记录 。调用时执行以下步骤:
1. 设 realmRec 为一个新的 范围记录 。
2. 执行 CreateIntrinsics (realmRec )。
3. 将 realmRec .[[AgentSignifier]]
设置为 AgentSignifier ()。
4. 将 realmRec .[[GlobalObject]] 设置为
undefined 。
5. 将 realmRec .[[GlobalEnv]] 设置为
undefined 。
6. 将 realmRec .[[TemplateMap]]
设置为一个新的空 列表 。
7. 返回 realmRec 。
9.3.2 创建内置对象(CreateIntrinsics) ( realmRec )
抽象操作 CreateIntrinsics 接受参数 realmRec (一个 范围记录 )并返回
unused 。调用时执行以下步骤:
1. 将 realmRec .[[Intrinsics]]
设置为一个新的 记录 。
2. 使用 表
6 中列出的值设置
realmRec .[[Intrinsics]]
的字段。这些字段名称是表的第一列中列出的名称。每个字段的值是一个新的对象值,按照规范中的定义完全递归地填充属性值。这些对象的创建顺序必须避免对尚未创建的对象的依赖。
3. 执行 AddRestrictedFunctionProperties (realmRec .[[Intrinsics]] .[[%Function.prototype% ]],
realmRec )。
4. 返回 unused 。
9.3.3 设置范围全局对象(SetRealmGlobalObject) ( realmRec ,
globalObj , thisValue )
抽象操作 SetRealmGlobalObject 接受参数 realmRec (一个 范围记录 )、globalObj (一个对象或
undefined ),以及 thisValue (一个对象或 undefined ),并返回
unused 。调用时执行以下步骤:
1. 如果 globalObj 是 undefined ,则:
a. 设 intrinsics 为 realmRec .[[Intrinsics]] 。
b. 将 globalObj 设置为 OrdinaryObjectCreate (intrinsics .[[%Object.prototype% ]])。
2. 断言 :globalObj 是 一个对象 。
3. 如果 thisValue 是 undefined ,则将
thisValue 设置为 globalObj 。
4. 将 realmRec .[[GlobalObject]] 设置为
globalObj 。
5. 设 newGlobalEnv 为 NewGlobalEnvironment (globalObj ,
thisValue )。
6. 将 realmRec .[[GlobalEnv]] 设置为
newGlobalEnv 。
7. 返回 unused 。
9.3.4 设置默认全局绑定(SetDefaultGlobalBindings) ( realmRec )
抽象操作 SetDefaultGlobalBindings 接受参数 realmRec (一个 范围记录 )并返回一个 正常完成的对象 或
一个 抛出完成 。调用时执行以下步骤:
1. 设 global 为 realmRec .[[GlobalObject]] 。
2. 对于在 第 19 章 中指定的全局对象的每个属性,执行:
a. 设 name 为属性名称的字符串值。
b. 设 desc 为该属性的完全填充的数据 属性描述符 ,包含该属性的指定属性。对于
第 19.2
章 、
第 19.3
章 或
第 19.4
章 中列出的属性,其 [[Value]] 属性的值是对应的内置对象。
c. 执行 ? DefinePropertyOrThrow (global , name ,
desc )。
3. 返回 global 。
9.4 执行上下文(Execution Contexts)
执行上下文 是一个规范设备,用于跟踪 ECMAScript 实现对代码的运行时评估。在任何时候,每个
代理
至多只有一个正在实际执行代码的执行上下文。这被称为该 代理 的 正在运行的执行上下文 。在此规范中的所有对 正在运行的执行上下文 的引用都指的是 围绕的代理 的 正在运行的执行上下文 。
执行上下文堆栈
用于跟踪执行上下文。正在运行的执行上下文 始终是该堆栈的顶部元素。每当控制从当前
正在运行的执行上下文
关联的可执行代码转移到与该执行上下文无关的可执行代码时,都会创建一个新的执行上下文。新创建的执行上下文会被推送到堆栈顶部,成为 正在运行的执行上下文 。
执行上下文包含所有跟踪其关联代码执行进度的必要实现特定状态。每个执行上下文至少有 表
25 中列出的状态组件。
表 25: 所有执行上下文的状态组件
评估 代码时 正在运行的执行上下文 可能会在此规范中定义的各个点暂停。一旦
正在运行的执行上下文 被暂停,不同的执行上下文可能成为
正在运行的执行上下文
并开始评估其代码。稍后,暂停的执行上下文可能再次成为 正在运行的执行上下文
并在先前暂停的点继续评估其代码。正在运行的执行上下文
状态在执行上下文之间的转换通常以堆栈样式的后进先出方式进行。然而,一些 ECMAScript 特性需要 正在运行的执行上下文 的非
LIFO 转换。
范围 组件的值也被称为
当前范围记录 。正在运行的执行上下文
的函数组件的值也被称为 活动函数对象 。
ECMAScript 代码执行上下文 具有 表
26 中列出的附加状态组件。
表 26: ECMAScript 代码执行上下文的附加状态组件
执行上下文的词法环境和变量环境组件始终是 环境记录 。
表示生成器评估的执行上下文具有 表
27 中列出的附加状态组件。
表 27: 生成器执行上下文的附加状态组件
组件
目的
生成器
此 执行上下文 正在评估的生成器。
在大多数情况下,仅由此规范中的算法直接操作 正在运行的执行上下文 (执行上下文堆栈
的顶部)。因此,当未注明时使用术语“词法环境”和“变量环境”,它们是指 正在运行的执行上下文 的这些组件。
执行上下文纯粹是一个规范机制,不需要对应于 ECMAScript 实现的任何特定制品。ECMAScript 代码不可能直接访问或观察到执行上下文。
9.4.1 GetActiveScriptOrModule ( )
抽象操作 GetActiveScriptOrModule 不接受参数,并返回 脚本记录 、模块记录 或
null 。它用于基于 正在运行的执行上下文
确定正在运行的脚本或模块。调用时执行以下步骤:
1. 如果 执行上下文堆栈 为空,则返回
null 。
2. 设 ec 为 执行上下文堆栈
中最顶部的 执行上下文 ,其 ScriptOrModule 组件不为
null 。
3. 如果不存在这样的 执行上下文 ,则返回
null 。否则,返回 ec 的 ScriptOrModule。
9.4.2 ResolveBinding ( name [ , env ] )
抽象操作 ResolveBinding 接受参数 name (一个字符串)和可选参数 env (一个 环境记录 或
undefined ),并返回 正常完成记录 ,包含一个
引用记录 或一个
抛出完成记录 。它用于确定
name 的绑定。env 可以用于显式提供要搜索绑定的 环境记录 。调用时执行以下步骤:
1. 如果未提供 env 或 env 为
undefined ,则
a. 将 env 设置为 正在运行的执行上下文 的词法环境。
2. 断言 :env 是一个 环境记录 。
3. 如果正在评估的语法生成的 源文本匹配
包含在 严格模式代码 中,则将 strict
设置为 true ;否则将 strict 设置为 false 。
4. 返回 ? GetIdentifierReference (env , name ,
strict )。
注
ResolveBinding 的结果始终是一个 引用记录 ,其 [[ReferencedName]] 字段是 name 。
9.4.3 GetThisEnvironment ( )
抽象操作 GetThisEnvironment 不接受参数,并返回一个 环境记录 。它找到当前提供 this
绑定的 环境记录 。调用时执行以下步骤:
1. 将 env 设置为 正在运行的执行上下文
的词法环境。
2. 重复以下步骤,直到条件不成立为止:
a. 让 exists 为 env .HasThisBinding()。
b. 如果 exists 为 true ,则返回
env 。
c. 将 outer 设置为 env .[[OuterEnv]] 。
d. 断言 :outer 不是
null 。
e. 将 env 设置为 outer 。
注
步骤 2 中的循环将始终终止,因为环境列表总是以具有
this
绑定的全局环境结束。
9.4.4 ResolveThisBinding ( )
抽象操作 ResolveThisBinding 不接受参数,并返回 正常完成记录 ,包含一个
ECMAScript 语言值 或一个
抛出完成记录 。它使用
正在运行的执行上下文 的词法环境确定
this
的绑定。调用时执行以下步骤:
1. 设 envRec 为 GetThisEnvironment ()。
2. 返回 ? envRec .GetThisBinding()。
9.4.5 GetNewTarget ( )
抽象操作 GetNewTarget 不接受参数,并返回一个对象或 undefined 。它使用 正在运行的执行上下文 的词法环境确定 NewTarget
值。调用时执行以下步骤:
1. 设 envRec 为 GetThisEnvironment ()。
2. 断言 :envRec 具有 [[NewTarget]] 字段。
3. 返回 envRec .[[NewTarget]] 。
9.4.6 GetGlobalObject ( )
抽象操作 GetGlobalObject 不接受参数并返回一个对象。它返回由当前 正在运行的执行上下文 使用的 全局对象 。调用时执行以下步骤:
1. 设 currentRealm 为 当前范围记录 。
2. 返回 currentRealm .[[GlobalObject]] 。
9.5 Jobs and Host Operations to Enqueue Jobs
作业 是一个无参数的抽象闭包 ,在没有其他 ECMAScript
计算正在进行时启动 ECMAScript 计算。
作业 由 ECMAScript
宿主环境 在特定的代理 中调度执行。本规范描述了宿主挂钩 HostEnqueueGenericJob ,
HostEnqueueFinalizationRegistryCleanupJob ,
HostEnqueuePromiseJob 和
HostEnqueueTimeoutJob 来调度作业。这个规范中的宿主挂钩 按调度作业时附加的约束进行组织。宿主 可以定义其他抽象操作 来调度作业。这些操作接受一个作业 抽象闭包 和一个范围 (一个范围记录 或null )作为参数。如果提供了范围记录 ,这些操作会在提供的范围 中调度作业,以由拥有范围 的代理 在将来的某个时间执行。如果提供的是null ,则该作业不会执行
ECMAScript 代码。其实现必须符合以下要求:
注 1
宿主环境 不需要
以统一的方式对待
作业 的调度。例如,网络浏览器和 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 的默认实现在调用时执行以下步骤:
1. 返回作业回调记录 { [[Callback]] :
callback ,[[HostDefined]] : empty }。
不是网络浏览器的 ECMAScript 宿主必须使用 HostMakeJobCallback 的默认实现。
注
这在将回调传递给负责其最终调度和运行的函数时调用。例如,promise.then(thenAction)
在调用Promise.prototype.then
时调用
MakeJobCallback
在调用Promise.prototype.then
时调用 MakeJobCallback,而不是在调度反应作业时。
9.5.3 HostCallJobCallback ( jobCallback , V ,
argumentsList )
宿主定义的 抽象操作 HostCallJobCallback
接受参数jobCallback (一个作业回调记录 ),V (一个ECMAScript
语言值 )和argumentsList (一个列表 由 ECMAScript
语言值组成)并返回正常完成 ,其中包含一个ECMAScript 语言值 或一个抛出完成 。
HostCallJobCallback 的实现必须符合以下要求:
它必须执行并返回调用 (jobCallback .[[Callback]] ,V ,argumentsList )的结果。
注
此要求意味着宿主不能更改本规范中定义的函数对象的[[Call]] 行为。
HostCallJobCallback 的默认实现在调用时执行以下步骤:
1. 断言 :IsCallable (jobCallback .[[Callback]] ) 为true 。
2. 返回?调用 (jobCallback .[[Callback]] ,V ,argumentsList )的结果。
不是网络浏览器的 ECMAScript 宿主必须使用 HostCallJobCallback 的默认实现。
9.5.4 HostEnqueueGenericJob ( job , realm )
宿主定义的 抽象操作 HostEnqueueGenericJob
接受参数job (一个作业 的抽象闭包 )和realm (一个范围记录 )并返回unused 。它将job 调度到realm 所指示的代理的realm 中,以便在将来的某个时间执行。这些抽象闭包旨在不受附加约束(如优先级和顺序)调度。
HostEnqueueGenericJob 的实现必须符合9.5 中的要求。
9.5.5 HostEnqueuePromiseJob ( job , realm )
宿主定义的 抽象操作 HostEnqueuePromiseJob
接受参数job (一个作业 的抽象闭包 )和realm (一个范围记录 或null )并返回unused 。它将job 调度到将来的某个时间执行。用于该算法的抽象闭包旨在与处理
Promise 相关,或者以与 Promise 处理操作同等的优先级进行调度。
HostEnqueuePromiseJob 的实现必须符合9.5 中的要求以及以下内容:
注
通过NewPromiseResolveThenableJob 返回的作业的realm 通常是通过调用GetFunctionRealm 在then 函数对象上的结果。通过NewPromiseReactionJob 返回的作业的realm 通常是通过调用GetFunctionRealm 在处理程序不是undefined 时的结果。如果处理程序是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 。它将timeoutJob 调度到realm 所指示的代理的realm 中,以便在至少milliseconds 毫秒后执行。
HostEnqueueTimeoutJob 的实现必须符合9.5 中的要求。
9.6 InitializeHostDefinedRealm ( )
抽象操作 InitializeHostDefinedRealm 不接受任何参数,返回一个包含 正常完成 的
unused 或者一个 抛出完成 。调用时,它执行以下步骤:
1. 让 realm 为 CreateRealm () 的结果。
2. 让 newContext 为一个新的 执行上下文 。
3. 将 newContext 的 Function 设置为 null 。
4. 将 newContext 的 Realm 设置为 realm 。
5. 将 newContext 的 ScriptOrModule 设置为 null 。
6. 将 newContext 推入 执行上下文栈 ;newContext
现在是 运行中的执行上下文 。
7. 如果 宿主 需要使用一个 特殊对象 作为 realm
的 全局对象 ,则让 global 为以
宿主定义 的方式创建的此类对象。否则,让 global 为
undefined ,表示应创建一个 普通对象 作为 全局对象 。
8. 如果 宿主 需要 this
绑定在 realm
的全局作用域中返回一个不同于 全局对象 的对象,则让 thisValue 为以
宿主定义 的方式创建的此类对象。否则,让 thisValue
为 undefined ,表示 realm 的全局 this
绑定应为 全局对象 。
9. 执行 SetRealmGlobalObject (realm ,
global , thisValue )。
10. 让 globalObj 为 ? SetDefaultGlobalBindings (realm ) 的结果。
11. 在 globalObj 上创建任何 宿主定义 的全局对象 属性。
12. 返回 unused 。
9.7 Agents
一个代理 包括一组ECMAScript执行上下文 、一个执行上下文栈 、一个运行中的执行上下文 、一个代理记录 和一个执行线程 。除了执行线程 之外,代理 的组成部分完全属于该代理 。
一个代理 的执行线程 独立于其他代理 在其执行上下文 上执行算法步骤,除非一个执行线程 可被多个代理 共享,前提是共享该线程的代理 没有代理记录 的[[CanBlock]] 字段为true 。
注1
一些网络浏览器会在多个不相关的浏览器窗口标签页之间共享单个执行线程 。
当一个代理 的执行线程 正在执行算法步骤时,该代理 就是这些步骤的外围代理 。这些步骤使用外围代理 来访问在代理 内保存的规范级执行对象:运行中的执行上下文 、执行上下文栈 和代理记录 的字段。
一个代理标识符 是一个全局唯一的、不透明的值,用于标识一个代理 。
表29: 代理记录 字段
字段名
值
含义
[[LittleEndian]]
布尔值
在算法GetValueFromBuffer 和SetValueInBuffer 中需要时,计算isLittleEndian 参数的默认值。该选择是实现定义 的,应该是对实现最有效的替代方案。一旦该值被观察到,它就不能改变。
[[CanBlock]]
布尔值
确定代理 是否可以阻塞。
[[Signifier]]
一个代理标识符
唯一标识其代理 在其代理集群 中的位置。
[[IsLockFree1]]
布尔值
如果对一个字节大小值的原子操作是无锁的,则为true ,否则为false 。
[[IsLockFree2]]
布尔值
如果对两字节大小值的原子操作是无锁的,则为true ,否则为false 。
[[IsLockFree8]]
布尔值
如果对八字节大小值的原子操作是无锁的,则为true ,否则为false 。
[[CandidateExecution]]
一个候选执行 记录
参见内存模型 。
[[KeptAlive]]
一个列表 ,包括对象或符号
最初是一个新的空列表 ,表示在当前任务 结束前需要保持存活的对象和/或符号的列表。
一旦[[Signifier]] 、[[IsLockFree1]] 和[[IsLockFree2]] 的值被任何代理 在其代理集群 中观察到,它们就不能改变。
注2
[[IsLockFree1]] 和[[IsLockFree2]] 的值不一定由硬件决定,还可能反映出可能随时间和不同ECMAScript实现而变化的实现选择。
没有[[IsLockFree4]] 字段:四字节原子操作总是无锁的。
实际上,如果一个原子操作的实现使用了任何类型的锁,则该操作就不是无锁的。无锁不意味着无等待:没有关于完成无锁原子操作需要多少机器步骤的上限。
原子访问大小为n 是无锁的,并不意味着对非原子访问大小为n 的访问有任何暗示,特别是,非原子访问仍可能作为一系列单独的内存访问执行。详见ReadSharedMemory 和WriteSharedMemory 。
注3
一个代理 是一个规范机制,不必对应于ECMAScript实现的任何特定工件。
9.7.1 AgentSignifier ( )
抽象操作 AgentSignifier 不接受任何参数,并返回一个代理标识符 。调用时,它执行以下步骤:
1. 让 AR 为代理记录 ,属于外围代理 。
2. 返回 AR .[[Signifier]] 。
9.7.2 AgentCanSuspend ( )
抽象操作 AgentCanSuspend 不接受任何参数,并返回一个布尔值。调用时,它执行以下步骤:
1. 让 AR 为代理记录 ,属于外围代理 。
2. 返回 AR .[[CanBlock]] 。
注
在某些环境中,允许给定代理 挂起可能是不合理的。例如,在网络浏览器环境中,可能不允许挂起文档的主事件处理线程,同时仍然允许工作线程的事件处理线程挂起。
9.8 代理集群
一个代理集群 是可以通过操作共享内存进行通信的代理 的最大集合。
注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.9 前进进度
对于一个代理 来说,前进进度 是指其根据本规范执行评估步骤。
当代理 的运行执行上下文 同步且无限期地等待外部事件时,该代理会变得阻塞 。只有其代理记录 的[[CanBlock]] 字段为true 的代理 才会以这种方式阻塞。一个非阻塞 的代理 是指不阻塞的代理。
实现必须确保:
每个拥有专用执行线程 的非阻塞代理 最终会取得前进进度
在共享执行线程 的一组代理 中,至少有一个代理 最终会取得前进进度
一个代理 不会导致另一个代理 变得阻塞,除非通过提供阻塞的显式API。
注
这与内存模型 中的活性保证一起,确保所有seq-cst 写操作最终会对所有代理 可见。
9.10 WeakRef 和 FinalizationRegistry 目标的处理模型
9.10.1 目标
本规范不保证任何对象或符号将被垃圾回收。对于那些不是存活的 对象或符号,可能在很长一段时间后或永远不会被释放。因此,本规范在描述垃圾回收触发的行为时使用了“可能”一词。
WeakRefs 和FinalizationRegistrys 的语义基于两个在特定时间点发生的操作:
这些操作(ClearKeptObjects 和CleanupFinalizationRegistry )不会中断同步的
ECMAScript 执行。由于宿主 可能会组装更长的同步 ECMAScript 执行运行,本规范将ClearKeptObjects 和CleanupFinalizationRegistry 的调度延迟到宿主环境 。
一些 ECMAScript 实现包括在后台运行的垃圾回收器实现,包括 ECMAScript 空闲时。让宿主环境 调度CleanupFinalizationRegistry 允许它恢复
ECMAScript 执行以运行终结器工作,这可能释放被占用的值,从而减少整体内存使用。
9.10.2 存活性
对于某些对象和/或符号的集合S ,相对于S 的假设的 WeakRef-oblivious 执行是指抽象操作WeakRefDeref 的执行,该操作始终返回undefined 。
注 1
WeakRef -obliviousness
与存活性共同捕捉了两个概念。其一,
WeakRef 本身不会使其引用保持存活。其二,存活性的循环不意味着一个值是存活的。具体来说,如果确定
v 的存活性取决于确定
WeakRef 引用
r 的存活性,
r 的存活性不能假定
v 的存活性,这将是循环推理。
注 2
WeakRef -obliviousness
是在对象或符号集合上定义的,以解释循环。如果它在单个值上定义,那么一个在循环中的
WeakRef 引用将被视为存活,即使它的身份只是通过循环中的其他
WeakRef 引用观察到的。
注 3
通俗地说,我们认为单个对象或符号是存活的,如果包含它的每个集合都是存活的。
在评估过程中,如果对象和/或符号的集合S 满足以下任一条件,则被认为是存活的 :
S 中的任何元素都包含在任何代理 的[[KeptAlive]] 列表 中。
存在一个有效的未来假设的 WeakRef-oblivious 执行,该执行观察S 中任何值的身份。
注 4
上述第二个条件旨在捕捉这样的直觉:如果通过非
WeakRef 方式观察到一个值的身份,那么该值是存活的。可以通过观察严格的相等比较或观察将值用作
Map 中的键来观察值的身份。
注 5
对象或符号在字段、内部槽或属性中的存在并不意味着该值是存活的。例如,如果问题中的值从未传递回程序,则无法观察到它。
这是 WeakMap 中的键、WeakSet 的成员以及[[WeakRefTarget]] 和[[UnregisterToken]] 字段在FinalizationRegistry 单元记录中的情况。
上述定义意味着,如果 WeakMap 中的键不是存活的,则其对应的值也不一定是存活的。
注 6
存活性是保证引擎不清空哪些
WeakRefs 的下限。此处定义的存活性是不可判定的。在实践中,引擎使用保守的近似方法,例如可达性。预计会有显著的实现灵活性。
9.10.3 执行
在任何时候,如果对象和/或符号的集合S 不是存活的 ,ECMAScript 实现可以原子地执行以下步骤:
1. 对于S 的每个元素value ,执行以下操作
a. 对于每个WeakRef ,如果ref 的[[WeakRefTarget]] 是value ,则执行以下操作
i. 将ref 的[[WeakRefTarget]] 设置为empty 。
b. 对于每个FinalizationRegistry ,如果fg 的[[Cells]] 包含一个记录 ,其中cell 的[[WeakRefTarget]] 是value ,则执行以下操作
i. 将cell 的[[WeakRefTarget]] 设置为empty 。
ii. 可选地,执行HostEnqueueFinalizationRegistryCleanupJob (fg )。
c. 对于每个 WeakMapmap ,如果map 的[[WeakMapData]] 包含一个记录 ,其中r 的[[Key]] 是value ,则执行以下操作
i. 将r 的[[Key]] 设置为empty 。
ii. 将r 的[[Value]] 设置为empty 。
d. 对于每个 WeakSetset ,如果set 的[[WeakSetData]] 包含value ,则执行以下操作
i. 用值为empty 的元素替换set 的[[WeakSetData]] 中值为value 的元素。
注 1
结合存活性的定义,本条款规定了实现可以应用的关于WeakRefs 的优化。
有可能在不观察对象身份的情况下访问对象。允许对非逃逸对象的属性进行死变量消除和标量替换等优化,因此这些优化可以可观察地清空指向这些对象的WeakRefs 。
另一方面,如果可以观察到对象的身份,并且该对象位于WeakRef 的[[WeakRefTarget]] 内部槽中,则禁止进行可观察地清空WeakRef 的优化。
由于调用HostEnqueueFinalizationRegistryCleanupJob 是可选的,注册在FinalizationRegistry 中的对象不一定是存活的 。实现可以因任何原因省略FinalizationRegistry 回调,例如,如果FinalizationRegistry 本身变得死掉,或如果应用程序正在关闭。
注 2
实现没有义务为最大集合的非存活 对象或符号清空WeakRefs 。
如果实现选择一个非存活 集合S 来清空WeakRefs ,则此定义要求它同时清空S 中所有值的WeakRefs 。换句话说,实现不符合规范的行为是清空指向值v 的WeakRef ,而不清空其他可能导致观察到v 值的WeakRefs 。
9.10.4 宿主钩子
9.10.4.1 HostEnqueueFinalizationRegistryCleanupJob
(finalizationRegistry )
宿主定义的 抽象操作
HostEnqueueFinalizationRegistryCleanupJob 接受参数finalizationRegistry (一个FinalizationRegistry )并返回unused 。
让cleanupJob 成为一个新的作业 抽象闭包 ,没有参数,捕获finalizationRegistry 并在调用时执行以下步骤:
1. 令cleanupResult 为完成 (CleanupFinalizationRegistry (finalizationRegistry ))。
2. 如果cleanupResult 是一个异常完成 ,执行任何宿主定义的 步骤来报告错误。
3. 返回unused 。
HostEnqueueFinalizationRegistryCleanupJob 的实现会安排在将来的某个时间执行cleanupJob ,如果可能的话。它还必须符合9.5 中的要求。
9.11 ClearKeptObjects ( )
抽象操作 ClearKeptObjects 不接受任何参数并返回 unused 。期望 ECMAScript 实现会在一系列同步的 ECMAScript 执行完成时调用
ClearKeptObjects。调用该操作时执行以下步骤:
1. 让 agentRecord 成为 周围代理 的 代理记录 。
2. 将 agentRecord .[[KeptAlive]]
设置为一个新的空的 列表 。
3. 返回 unused 。
9.12 AddToKeptObjects ( value )
抽象操作 AddToKeptObjects 接受参数 value (一个对象或符号)并返回 unused 。调用该操作时执行以下步骤:
1. 让 agentRecord 成为 周围代理 的 代理记录 。
2. 将 value 添加到 agentRecord .[[KeptAlive]] 。
3. 返回 unused 。
注
当抽象操作 AddToKeptObjects 被调用并传入目标对象或符号时,它会将目标添加到一个列表中,该列表会强引用该目标,直到调用
ClearKeptObjects 。
9.13 CleanupFinalizationRegistry ( finalizationRegistry )
抽象操作 CleanupFinalizationRegistry 接受参数 finalizationRegistry (一个 FinalizationRegistry ),并返回
正常完成记录,包含
unused 或 抛出完成记录 。调用该操作时执行以下步骤:
1. 断言 :finalizationRegistry 具有 [[Cells]] 和 [[CleanupCallback]] 内部槽。
2. 让 callback 为 finalizationRegistry .[[CleanupCallback]] 。
3. 当 finalizationRegistry .[[Cells]]
包含一个 记录
cell ,其 [[WeakRefTarget]] 为 empty 时,实现可以执行以下步骤:
a. 选择任意这样的 cell 。
b. 从 finalizationRegistry .[[Cells]] 中移除 cell 。
c. 执行 ? HostCallJobCallback (callback ,
undefined , « cell .[[HeldValue]] »)。
4. 返回 unused 。
9.14 CanBeHeldWeakly ( v )
抽象操作 CanBeHeldWeakly 接受参数 v (一个 ECMAScript 语言值 ),并返回一个布尔值。仅当
v 适合用作弱引用时,它才返回 true 。只有适合用作弱引用的值才可以作为 WeakMap 的键、WeakSet 的元素、WeakRef 的目标,或 FinalizationRegistry
的目标之一。调用该操作时执行以下步骤:
1. 如果 v 是一个对象 ,返回 true 。
2. 如果 v 是一个符号 ,并且
KeyForSymbol (v ) 是
undefined ,返回 true 。
3. 返回 false 。
注
没有 语言身份 的语言值可以在没有先前引用的情况下显现出来,不适合用作弱引用。通过
Symbol.for
产生的符号值与其他符号值不同,它没有语言身份,因此不适合用作弱引用。众所周知的符号
可能永远不会被收集,但仍被视为适合用作弱引用,因为它们数量有限,可以通过多种实现方法进行管理。然而,在 活动 WeakMap
中与众所周知符号关联的任何值都不太可能被收集,并且可能在实现中“泄漏”内存资源。
10 普通对象和异域对象的行为
10.1 普通对象的内部方法和内部槽
所有的 普通对象 都有一个名为 [[Prototype]] 的内部槽。这个内部槽的值可以是 null 或一个对象,用于实现继承。假设某个名为 P
的属性在一个 普通对象 O 中缺失,但在其 [[Prototype]] 对象上存在。如果 P 指向 数据属性 ,则 O
会继承该属性以进行读取操作,使其行为如同 P 是 O 的一个属性一样。如果 P 指向 [[Prototype]] 对象上的一个可写的 数据属性 ,则在 O 上设置 P
的访问将会创建一个新的名为 P 的 数据属性 。如果 P 指向 [[Prototype]] 对象上的一个不可写的 数据属性 ,则在 O 上设置 P
的访问将会失败。如果 P 指向 访问器属性 ,该访问器将被 O 继承,以进行读取和设置操作。
每个 普通对象 都有一个布尔值的 [[Extensible]] 内部槽,用于满足 6.1.7.3
中规定的与可扩展性相关的内部方法不变性。也就是说,一旦对象的 [[Extensible]] 内部槽的值被设置为
false ,就不能再向对象添加属性,也不能修改对象的 [[Prototype]] 内部槽的值,或者随后将 [[Extensible]] 的值更改为 true 。
在以下算法描述中,假设 O 是一个 普通对象 ,P 是一个 属性键 值,V 是任何 ECMAScript 语言值 ,而
Desc 是一个 属性描述符 记录。
每个 普通对象
的内部方法都委托给一个同名的抽象操作。如果这样的抽象操作依赖于另一个内部方法,那么内部方法将会在 O 上被调用,而不是直接调用同名的抽象操作。这些语义确保了 异域对象
在应用普通对象的内部方法时,其被重写的内部方法会被调用。
10.1.1 [[GetPrototypeOf]] ( )
[[GetPrototypeOf]] 内部方法用于一个 普通对象 O ,不接受任何参数,返回一个 正常的完成记录 ,其值为一个对象或
null 。调用时执行以下步骤:
1. 返回 OrdinaryGetPrototypeOf (O )。
10.1.1.1 OrdinaryGetPrototypeOf ( O )
抽象操作 OrdinaryGetPrototypeOf 接受一个参数 O (一个对象),并返回一个对象或 null 。调用时执行以下步骤:
1. 返回 O .[[Prototype]] 。
10.1.2 [[SetPrototypeOf]] ( V )
[[SetPrototypeOf]] 内部方法用于一个 普通对象 O ,接受一个参数
V (一个对象或 null ),并返回一个 正常的完成记录 ,其值为布尔值。调用时执行以下步骤:
1. 返回 OrdinarySetPrototypeOf (O ,
V )。
10.1.2.1 OrdinarySetPrototypeOf ( O , V )
抽象操作 OrdinarySetPrototypeOf 接受两个参数:O (一个对象)和 V (一个对象或
null ),并返回一个布尔值。调用时执行以下步骤:
1. 将 current 设为 O .[[Prototype]] 。
2. 如果 SameValue (V ,
current ) 为 true ,则返回 true 。
3. 将 extensible 设为 O .[[Extensible]] 。
4. 如果 extensible 为 false ,则返回
false 。
5. 将 p 设为 V 。
6. 将 done 设为 false 。
7. 重复以下步骤,直到 done 为
true :
a. 如果 p 为 null ,则
i. 将 done 设为 true 。
b. 否则,如果 SameValue (p ,
O ) 为 true ,则
i. 返回 false 。
c. 否则,
i. 如果 p .[[GetPrototypeOf]] 不是在 普通对象
内部方法中定义的 10.1.1 ,则将
done 设为 true 。
ii. 否则,将 p 设为 p .[[Prototype]] 。
8. 将 O .[[Prototype]] 设为
V 。
9. 返回 true 。
注
步骤 7
中的循环保证了在原型链中只包含使用 普通对象 定义的 [[GetPrototypeOf]] 和 [[SetPrototypeOf]] 的对象时,不会出现循环。
10.1.3 [[IsExtensible]] ( )
[[IsExtensible]] 内部方法用于一个 普通对象 O ,不接受参数,并返回一个 正常的完成记录 ,其值为布尔值。调用时执行以下步骤:
1. 返回 OrdinaryIsExtensible (O )。
10.1.3.1 OrdinaryIsExtensible ( O )
抽象操作 OrdinaryIsExtensible 接受一个参数 O (一个对象),并返回一个布尔值。调用时执行以下步骤:
1. 返回 O .[[Extensible]] 。
10.1.4 [[PreventExtensions]] ( )
[[PreventExtensions]] 内部方法用于一个 普通对象 O ,不接受参数,并返回一个 正常的完成记录 ,其值为
true 。调用时执行以下步骤:
1. 返回 OrdinaryPreventExtensions (O )。
10.1.4.1 OrdinaryPreventExtensions ( O )
抽象操作 OrdinaryPreventExtensions 接受一个参数 O (一个对象),并返回 true 。调用时执行以下步骤:
1. 将 O .[[Extensible]] 设置为
false 。
2. 返回 true 。
10.1.5 [[GetOwnProperty]] ( P )
[[GetOwnProperty]] 内部方法用于一个 普通对象 O ,接受一个参数 P (一个
属性键 ),并返回一个 正常的完成记录 ,其值可以是
属性描述符 或
undefined 。调用时执行以下步骤:
1. 返回 OrdinaryGetOwnProperty (O ,
P )。
10.1.5.1 OrdinaryGetOwnProperty ( O , P )
抽象操作 OrdinaryGetOwnProperty 接受两个参数 O (一个对象)和 P (一个 属性键 ),并返回一个 属性描述符 或
undefined 。调用时执行以下步骤:
1. 如果 O 没有键为 P 的自身属性,则返回
undefined 。
2. 创建一个新的 属性描述符
D ,其字段为空。
3. 获取 O 自身属性中键为 P 的属性 X 。
4. 如果 X 是一个 数据属性 ,则:
a. 将 D .[[Value]] 设置为
X 的 [[Value]] 属性值。
b. 将 D .[[Writable]] 设置为
X 的 [[Writable]] 属性值。
5. 否则:
a. 断言 :X 是一个 访问器属性 。
b. 将 D .[[Get]] 设置为
X 的 [[Get]] 属性值。
c. 将 D .[[Set]] 设置为
X 的 [[Set]] 属性值。
6. 将 D .[[Enumerable]] 设置为
X 的 [[Enumerable]] 属性值。
7. 将 D .[[Configurable]] 设置为
X 的 [[Configurable]] 属性值。
8. 返回 D 。
10.1.6 [[DefineOwnProperty]] ( P ,
Desc )
普通对象的 [[DefineOwnProperty]] 内部方法接受两个参数:P (一个
属性
键 )和 Desc (一个
属性描述符 ),
并返回一个 正常完成 ,
包含一个布尔值或一个 抛出完成 。
调用时,它执行以下步骤:
1. 返回 ? OrdinaryDefineOwnProperty (O , P ,
Desc ).
10.1.6.1 OrdinaryDefineOwnProperty(O , P ,
Desc )
抽象操作 OrdinaryDefineOwnProperty 接受参数 O (一个对象)、P (一个属性键 ),和
Desc (一个属性描述符 ),并返回一个包含 布尔值的正常完成或一个抛出完成 。当被调用时,它执行以下步骤:
1. 令 current 为 ? O .[[GetOwnProperty]] (P )。
2. 令 extensible 为 ? IsExtensible (O )。
3. 返回 ValidateAndApplyPropertyDescriptor (O ,
P , extensible , Desc , current )。
10.1.6.2 IsCompatiblePropertyDescriptor(Extensible ,
Desc , Current )
抽象操作 IsCompatiblePropertyDescriptor 接受参数 Extensible (一个布尔值)、Desc (一个属性描述符 ),和
Current (一个属性描述符 或
undefined ),并返回一个布尔值。当被调用时,它执行以下步骤:
1. 返回 ValidateAndApplyPropertyDescriptor (undefined ,
"" , Extensible , Desc , Current )。
10.1.6.3 ValidateAndApplyPropertyDescriptor(O , P ,
extensible , Desc , current )
抽象操作 ValidateAndApplyPropertyDescriptor 接受参数
O (一个对象或undefined )、P (一个属性键 )、extensible (一个布尔值)、Desc (一个属性描述符 ),和
current (一个属性描述符 或undefined ),并返回一个布尔值。只有当
Desc 可以作为具有指定扩展性 和当前属性current 的对象的属性应用时,同时保持不变量 时,它才返回
true 。当这种应用是可能的且O 不是undefined 时,它会为名为P 的属性执行该应用(如有必要,创建该属性)。当被调用时,它执行以下步骤:
1. 断言 :IsPropertyKey (P ) 是
true 。
2. 如果 current 是 undefined ,则
a. 如果 extensible 是 false ,返回
false 。
b. 如果 O 是 undefined ,返回
true 。
c. 如果 IsAccessorDescriptor (Desc )
是 true ,则
i. 为对象 O 创建一个名为 P 的存取器属性 ,其 [[Get]] 、[[Set]] 、[[Enumerable]] 和 [[Configurable]] 属性设置为
Desc 中相应字段的值,如果 Desc 有该字段,则设置为该字段的值,否则设置为属性的默认值 。
d. 否则,
i. 为对象 O 创建一个名为 P 的数据属性 ,其 [[Value]] 、[[Writable]] 、[[Enumerable]] 和 [[Configurable]] 属性设置为
Desc 中相应字段的值,如果 Desc 有该字段,则设置为该字段的值,否则设置为属性的默认值 。
e. 返回 true 。
3. 断言 :current 是一个完全填充的属性描述符 。
4. 如果 Desc 没有任何字段,返回 true 。
5. 如果 current .[[Configurable]] 是
false ,则
a. 如果 Desc 有一个 [[Configurable]] 字段且 Desc .[[Configurable]] 是 true ,返回 false 。
b. 如果 Desc 有一个 [[Enumerable]] 字段且 Desc .[[Enumerable]]
不等于 current .[[Enumerable]] ,返回 false 。
c. 如果 IsGenericDescriptor (Desc )
是 false 并且 IsAccessorDescriptor (Desc )
不等于 IsAccessorDescriptor (current ),返回
false 。
d. 如果 IsAccessorDescriptor (current )
是 true,则
i. 如果 Desc 有一个 [[Get]]
字段且 SameValue (Desc .[[Get]] , current .[[Get]] ) 是
false ,返回 false 。
ii. 如果 Desc 有一个 [[Set]] 字段且 SameValue (Desc .[[Set]] , current .[[Set]] ) 是
false ,返回 false 。
e. 否则,如果 current .[[Writable]] 是 false ,则
i. 如果 Desc 有一个 [[Writable]] 字段且 Desc .[[Writable]] 是
true ,返回 false 。
ii. 如果 Desc 有一个 [[Value]] 字段且 SameValue (Desc .[[Value]] , current .[[Value]] ) 是
false ,返回 false 。
6. 如果 O 不是 undefined ,则
a. 如果 IsDataDescriptor (current )
是 true 且 IsAccessorDescriptor (Desc )
是 true ,则
i. 如果 Desc 有一个 [[Configurable]] 字段,令 configurable 为 Desc .[[Configurable]] ;否则令 configurable 为 current .[[Configurable]] 。
ii. 如果 Desc 有一个 [[Enumerable]] 字段,令 enumerable 为 Desc .[[Enumerable]] ;否则令 enumerable 为 current .[[Enumerable]] 。
iii. 替换对象 O 中名为 P 的属性为一个存取器属性 ,其 [[Configurable]] 和 [[Enumerable]] 属性分别设置为
configurable 和 enumerable ,其 [[Get]] 和 [[Set]] 属性设置为 Desc 中相应字段的值,如果 Desc
有该字段,则设置为该字段的值,否则设置为属性的默认值 。
b. 否则,如果 IsAccessorDescriptor (current )
是 true 且 IsDataDescriptor (Desc )
是 true ,则
i. 如果 Desc 有一个 [[Configurable]] 字段,令 configurable 为 Desc .[[Configurable]] ;否则令 configurable 为 current .[[Configurable]] 。
ii. 如果 Desc 有一个 [[Enumerable]] 字段,令 enumerable 为 Desc .[[Enumerable]] ;否则令 enumerable 为 current .[[Enumerable]] 。
iii. 替换对象 O 中名为 P 的属性为一个数据属性 ,其 [[Configurable]] 和 [[Enumerable]] 属性分别设置为
configurable 和 enumerable ,其 [[Value]] 和 [[Writable]] 属性设置为 Desc 中相应字段的值,如果 Desc
有该字段,则设置为该字段的值,否则设置为属性的默认值 。
c. 否则,
i. 对于 Desc 的每个字段,将对象 O 中名为
P 的属性的相应属性设置为该字段的值。
7. 返回 true 。
10.1.7 [[HasProperty]] (P )
一个普通对象 的[[HasProperty]] 内部方法接受参数P (一个属性键 ),并返回一个包含 布尔值的正常完成或一个抛出完成 。当被调用时,它执行以下步骤:
1. 返回 ? OrdinaryHasProperty (O , P )。
10.1.7.1 OrdinaryHasProperty(O , P )
抽象操作 OrdinaryHasProperty 接受参数 O (一个对象)和 P (一个属性键 ),并返回一个包含 布尔值的正常完成或一个抛出完成 。当被调用时,它执行以下步骤:
1. 令 hasOwn 为 ? O .[[GetOwnProperty]] (P )。
2. 如果 hasOwn 不是 undefined ,返回
true 。
3. 令 parent 为 ? O .[[GetPrototypeOf]] ()。
4. 如果 parent 不是 null ,则
a. 返回 ? parent .[[HasProperty]] (P )。
5. 返回 false 。
10.1.8 [[Get]] ( P ,
Receiver
)
[[Get]] 内部方法用于一个 普通对象
O ,接受参数 P (一个 属性键 )和
Receiver (一个 ECMAScript 语言值 ),并返回一个
正常完成记录 ,其中包含一个
ECMAScript 语言值 ,或者一个
抛出完成记录 。调用时执行以下步骤:
1. 返回 ? OrdinaryGet (O , P , Receiver ).
10.1.8.1 OrdinaryGet ( O , P , Receiver )
抽象操作 OrdinaryGet 接受参数 O (一个对象)、P (一个 属性键 )和
Receiver (一个 ECMAScript 语言值 ),并返回一个
正常完成记录 ,其中包含一个
ECMAScript 语言值 ,或者一个
抛出完成记录 。调用时执行以下步骤:
1. 让 desc 等于 ? O .[[GetOwnProperty]] (P )。
2. 如果 desc 是 undefined ,则
a. 让 parent 等于 ? O .[[GetPrototypeOf]] ()。
b. 如果 parent 是 null ,返回
undefined 。
c. 返回 ? parent .[[Get]] (P , Receiver )。
3. 如果 IsDataDescriptor (desc )
是 true ,返回 desc .[[Value]] 。
4. 断言 : IsAccessorDescriptor (desc )
是 true 。
5. 让 getter 等于 desc .[[Get]] 。
6. 如果 getter 是 undefined ,返回
undefined 。
7. 返回 ? Call (getter , Receiver )。
10.1.9 [[Set]] ( P , V ,
Receiver )
普通对象(ordinary object )O 的 [[Set]] 内部方法接受三个参数:P (属性键),V (ECMAScript 语言值),和
Receiver (ECMAScript 语言值),并返回一个完成记录,可能是包含布尔值的正常完成记录,也可能是抛出异常的完成记录。调用时执行以下步骤:
1. 返回 ? OrdinarySet (O , P , V ,
Receiver )。
10.1.9.1 OrdinarySet ( O , P , V ,
Receiver )
抽象操作 OrdinarySet 接受四个参数:O (对象),P (属性键),V (ECMAScript 语言值),和
Receiver (ECMAScript 语言值),并返回一个完成记录,可能是包含布尔值的正常完成记录,也可能是抛出异常的完成记录。调用时执行以下步骤:
1. 让 ownDesc 为 ? O .[[GetOwnProperty]] (P )。
2. 返回 ? OrdinarySetWithOwnDescriptor (O , P ,
V , Receiver , ownDesc )。
10.1.9.2 OrdinarySetWithOwnDescriptor ( O , P ,
V , Receiver , ownDesc )
抽象操作 OrdinarySetWithOwnDescriptor 接受五个参数:O (对象),P (属性键),V (ECMAScript
语言值),Receiver (ECMAScript 语言值),和 ownDesc (属性描述符或
undefined ),并返回一个完成记录,可能是包含布尔值的正常完成记录,也可能是抛出异常的完成记录。调用时执行以下步骤:
1. 如果 ownDesc 为 undefined ,则:
a. 让 parent 为 ? O .[[GetPrototypeOf]] ()。
b. 如果 parent 不为 null ,则:
i. 返回 ? parent .[[Set]] (P ,
V , Receiver )。
c. 否则:
i. 将 ownDesc 设置为属性描述符 {[[Value]] : undefined , [[Writable]] : true , [[Enumerable]] : true , [[Configurable]] : true }。
2. 如果 IsDataDescriptor (ownDesc )
为 true ,则:
a. 如果 ownDesc .[[Writable]] 为
false ,返回 false 。
b. 如果 Receiver 不是一个对象 ,返回
false 。
c. 让 existingDescriptor 为 ? Receiver .[[GetOwnProperty]] (P )。
d. 如果 existingDescriptor 不为
undefined ,则:
i. 如果 IsAccessorDescriptor (existingDescriptor )
为 true ,返回 false 。
ii. 如果 existingDescriptor .[[Writable]] 为 false ,返回 false 。
iii. 让 valueDesc 为属性描述符 {[[Value]] : V }。
iv. 返回 ? Receiver .[[DefineOwnProperty]] (P , valueDesc )。
e. 否则:
i. Assert : Receiver 当前没有属性
P 。
ii. 返回 ? CreateDataProperty (Receiver , P ,
V )。
3. Assert : IsAccessorDescriptor (ownDesc )
为 true 。
4. 让 setter 为 ownDesc .[[Set]] 。
5. 如果 setter 为 undefined ,返回
false 。
6. 执行 ? Call (setter , Receiver , «V »)。
7. 返回 true 。
10.1.10 [[Delete]] ( P )
普通对象(ordinary object )O 的 [[Delete]] 内部方法接受参数 P (属性键 ),并返回一个包含布尔值的正常完成记录或一个抛出异常的完成记录。调用时执行以下步骤:
1. 返回 ? OrdinaryDelete (O , P )。
10.1.10.1 OrdinaryDelete ( O , P )
抽象操作 OrdinaryDelete 接受两个参数:O (对象)和 P (属性键 ),并返回一个包含布尔值的正常完成记录或一个抛出异常的完成记录。调用时执行以下步骤:
1. 让 desc 为 ? O .[[GetOwnProperty]] (P )。
2. 如果 desc 为 undefined ,返回
true 。
3. 如果 desc .[[Configurable]] 为
true ,则:
a. 从 O 中删除名称为 P 的自身属性。
b. 返回 true 。
4. 返回 false 。
10.1.11 [[OwnPropertyKeys]] ( )
普通对象(ordinary object )O 的 [[OwnPropertyKeys]] 内部方法不接受任何参数,并返回一个包含 列表 的正常完成记录,该列表包含
属性键 。调用时执行以下步骤:
1. 返回 OrdinaryOwnPropertyKeys (O )。
10.1.11.1 OrdinaryOwnPropertyKeys ( O )
抽象操作 OrdinaryOwnPropertyKeys 接受一个参数 O (对象),并返回一个包含 列表 的 属性键 。调用时执行以下步骤:
1. 让 keys 为一个新的空 列表 。
2. 对于 O 的每个自身 属性键
P ,如果 P 是 数组索引 ,按升序的数字索引顺序:
a. 将 P 添加到 keys 中。
3. 对于 O 的每个自身 属性键
P ,如果 P 是一个字符串 且
P 不是 数组索引 ,按属性创建的升序时间顺序:
a. 将 P 添加到 keys 中。
4. 对于 O 的每个自身 属性键
P ,如果 P 是一个符号 ,按属性创建的升序时间顺序:
a. 将 P 添加到 keys 中。
5. 返回 keys 。
10.1.12 OrdinaryObjectCreate ( proto [ ,
additionalInternalSlotsList ] )
抽象操作 OrdinaryObjectCreate 接受参数 proto (一个对象或 null )以及可选参数
additionalInternalSlotsList (一个 列表 ,包含内部槽的名称),并返回一个对象。它用于指定新的
普通对象
的运行时创建。additionalInternalSlotsList 包含必须作为对象一部分定义的附加内部槽的名称,除了 [[Prototype]] 和 [[Extensible]] 。如果未提供
additionalInternalSlotsList ,则使用一个新的空 列表 。调用时执行以下步骤:
1. 让 internalSlotsList 为 « [[Prototype]] , [[Extensible]] »。
2. 如果 additionalInternalSlotsList 存在,则将
internalSlotsList 设置为 列表连接 internalSlotsList
和 additionalInternalSlotsList 的结果。
3. 让 O 为 MakeBasicObject (internalSlotsList )。
4. 将 O .[[Prototype]] 设置为
proto 。
5. 返回 O 。
注
尽管 OrdinaryObjectCreate 仅调用 MakeBasicObject ,但它的使用传达了创建
普通对象
的意图,而不是一种特殊的对象。因此,在该规范中,它不会被任何算法调用,这些算法随后会以使结果变为非普通的方式修改对象的内部方法。创建 特殊对象 的操作直接调用 MakeBasicObject 。
10.1.13 OrdinaryCreateFromConstructor ( constructor ,
intrinsicDefaultProto [ , internalSlotsList ] )
抽象操作 OrdinaryCreateFromConstructor 接受参数 constructor (一个 构造函数 )和
intrinsicDefaultProto (一个字符串),以及可选参数 internalSlotsList (一个 列表 ,包含内部槽的名称),并返回一个对象或抛出异常。它创建一个
普通对象 ,其 [[Prototype]] 值从 构造函数 的 "prototype"
属性中获取(如果存在)。否则,使用由 intrinsicDefaultProto 指定的内建对象作为 [[Prototype]] 。internalSlotsList 包含必须作为对象一部分定义的附加内部槽的名称。如果未提供
internalSlotsList ,则使用一个新的空 列表 。调用时执行以下步骤:
1. 断言 : intrinsicDefaultProto
是本规范定义的内建对象的名称。对应的对象必须是一个内建对象,旨在作为对象的 [[Prototype]] 值。
2. 让 proto 为 ? GetPrototypeFromConstructor (constructor ,
intrinsicDefaultProto )。
3. 如果 internalSlotsList 存在,令 slotsList 为
internalSlotsList 。
4. 否则,令 slotsList 为一个新的空 列表 。
5. 返回 OrdinaryObjectCreate (proto ,
slotsList )。
10.1.14 GetPrototypeFromConstructor ( constructor ,
intrinsicDefaultProto )
抽象操作 GetPrototypeFromConstructor 接受参数 constructor (一个 函数对象 )和
intrinsicDefaultProto (一个字符串),并返回一个对象或抛出异常。它确定在创建与特定 构造函数 对应的对象时应使用的 [[Prototype]] 值。该值从 构造函数 的 "prototype"
属性中获取(如果存在)。否则,使用由 intrinsicDefaultProto 指定的内建对象作为 [[Prototype]] 。调用时执行以下步骤:
1. 断言 : intrinsicDefaultProto
是本规范定义的内建对象的名称。对应的对象必须是一个内建对象,旨在作为对象的 [[Prototype]] 值。
2. 令 proto 为 ? Get (constructor , "prototype" )。
3. 如果 proto 不是一个对象 ,则
a. 令 realm 为 ? GetFunctionRealm (constructor )。
b. 将 proto 设置为 realm 的名为
intrinsicDefaultProto 的内建对象。
4. 返回 proto 。
注
如果 constructor 没有提供 [[Prototype]] 值,则使用的默认值是从 领域 的
constructor 函数获取的,而不是从 正在执行的上下文 中获取。
10.1.15 RequireInternalSlot ( O , internalSlot )
抽象操作 RequireInternalSlot 接受参数 O (一个 ECMAScript
语言值 )和 internalSlot (一个内部槽名称),并返回一个正常的完成包含 unused
或一个抛出完成。除非 O 是一个对象 并且具有给定的内部槽,否则会抛出异常。调用时执行以下步骤:
1. 如果 O 不是一个对象 ,则抛出一个
TypeError 异常。
2. 如果 O 不具有一个 internalSlot 内部槽,则抛出一个
TypeError 异常。
3. 返回 unused 。
10.2 ECMAScript 函数对象
ECMAScript 函数对象 封装了参数化的 ECMAScript
代码,并将其封闭在词法环境中,支持对该代码的动态求值。一个 ECMAScript 函数对象 是一个 普通对象 ,并且具有与其他 普通对象 相同的内部槽和内部方法。一个 ECMAScript 函数对象 的代码可以是 严格模式代码 (见 11.2.2 )或 非严格模式代码 。一个 ECMAScript 函数对象 的代码是 严格模式代码 的,被称为 严格函数 。如果代码不是 严格模式代码 ,则称为 非严格函数 。
除了 [[Extensible]] 和 [[Prototype]] 外,ECMAScript 函数对象 还有在 表 30
中列出的内部槽。
表 30: ECMAScript 函数对象的内部槽
内部槽
类型
描述
[[Environment]]
一个 环境记录
函数封闭的 环境记录 。在评估函数代码时用作外部环境。
[[PrivateEnvironment]]
一个 PrivateEnvironment 记录
或 null
函数封闭的 PrivateEnvironment
记录 。如果该函数没有语法上包含在类中,则为 null 。在评估函数代码时,作为内部类的外部
PrivateEnvironment 使用。
[[FormalParameters]]
一个 解析节点
定义函数正式参数列表的源文本的根解析节点。
[[ECMAScriptCode]]
一个 解析节点
定义函数主体的源文本的根解析节点。
[[ConstructorKind]]
base 或 derived
函数是否是派生类 构造函数 。
[[Realm]]
一个 Realm 记录
函数创建的 realm ,提供在评估函数时访问的任何内建对象。
[[ScriptOrModule]]
一个 脚本记录 或 模块记录
函数创建的脚本或模块。
[[ThisMode]]
lexical 、strict 或 global
定义 this
引用在函数的正式参数和代码体内如何被解释。lexical 表示 this
指向词法上封闭函数的 this 值。strict 表示 this
值正好按照函数调用时提供的值使用。global 表示 this 值为
undefined 或 null 时解释为对 全局对象 的引用,其他的
this 值则首先传递给 ToObject 。
[[Strict]]
一个布尔值
如果这是一个 严格函数 ,则为
true ;如果这是一个 非严格函数 ,则为
false 。
[[HomeObject]]
一个对象
如果函数使用了 super
,这是提供 [[GetPrototypeOf]] 的对象,从而开始
super
属性的查找。
[[SourceText]]
一系列 Unicode 码点
定义函数的 源文本 。
[[Fields]]
一个 列表
的 ClassFieldDefinition
记录
如果函数是一个类,则这是一个列表,表示类的非静态字段及其对应的初始化器。
[[PrivateMethods]]
一个 列表
的 PrivateElements
如果函数是一个类,则这是一个列表,表示类的非静态私有方法和访问器。
[[ClassFieldInitializerName]]
一个字符串、一个符号、一个 私有名称 或
empty
如果函数作为类字段的初始化器创建,则用于 NamedEvaluation
的名称;否则为 empty 。
[[IsClassConstructor]]
一个布尔值
指示函数是否是一个类 构造函数 。如果为
true ,调用该函数的 [[Call]] 将立即抛出 TypeError
异常。
所有 ECMAScript 函数对象 都有这里定义的 [[Call]] 内部方法。此外,ECMAScript 函数如果也是 构造函数 ,则还有 [[Construct]] 内部方法。
10.2.1 [[Call]] ( thisArgument ,
argumentsList )
ECMAScript 函数对象 F 的 [[Call]] 内部方法接受参数 thisArgument (一个 ECMAScript 语言值 )和
argumentsList (一个 列表 ,包含 ECMAScript 语言值 ),并返回一个
正常完成 (包含一个
ECMAScript 语言值 )或者一个
抛出完成 。调用时执行以下步骤:
1. 让 callerContext 为 当前执行上下文 。
2. 让 calleeContext 为 PrepareForOrdinaryCall (F ,
undefined )。
3. 断言 : calleeContext 现在是 当前执行上下文 。
4. 如果 F .[[IsClassConstructor]] 为
true ,则
a. 让 error 为一个新创建的 TypeError 对象。
b. 注意:error 是在 calleeContext 中创建的,使用
F 关联的 领域记录 。
c. 从 执行上下文栈 中移除
calleeContext ,并将 callerContext 恢复为 当前执行上下文 。
d. 返回 ThrowCompletion (error )。
5. 执行 OrdinaryCallBindThis (F ,
calleeContext , thisArgument )。
6. 让 result 为 Completion (OrdinaryCallEvaluateBody (F ,
argumentsList ))。
7. 从 执行上下文栈 中移除
calleeContext ,并将 callerContext 恢复为 当前执行上下文 。
8. 如果 result 是一个 返回完成 ,返回
result .[[Value]] 。
9. ReturnIfAbrupt (result )。
10. 返回 undefined 。
注
当在步骤 7 中从 执行上下文栈 中移除
calleeContext 时,如果它是挂起的并被生成器保留以便以后恢复,则不得销毁它。
10.2.1.1 PrepareForOrdinaryCall ( F , newTarget )
抽象操作 PrepareForOrdinaryCall 接受参数 F (一个 ECMAScript 函数对象 )和
newTarget (一个对象或 undefined ),并返回一个 执行上下文 。它在调用时执行以下步骤:
1. 让 callerContext 为 当前执行上下文 。
2. 让 calleeContext 为一个新的 ECMAScript
代码执行上下文 。
3. 将 calleeContext 的函数设置为 F 。
4. 让 calleeRealm 为 F .[[Realm]] 。
5. 将 calleeContext 的 领域 设置为
calleeRealm 。
6. 将 calleeContext 的 ScriptOrModule 设置为 F .[[ScriptOrModule]] 。
7. 让 localEnv 为 NewFunctionEnvironment (F ,
newTarget )。
8. 将 calleeContext 的词法环境设置为 localEnv 。
9. 将 calleeContext 的变量环境设置为 localEnv 。
10. 将 calleeContext 的私有环境设置为 F .[[PrivateEnvironment]] 。
11. 如果 callerContext 尚未被挂起,则挂起 callerContext 。
12. 将 calleeContext 推入 执行上下文栈 ;calleeContext
现在是 当前执行上下文 。
13. 注意:此后产生的任何异常对象都与 calleeRealm 关联。
14. 返回 calleeContext 。
10.2.1.2 OrdinaryCallBindThis ( F , calleeContext ,
thisArgument )
抽象操作 OrdinaryCallBindThis 接受参数 F (一个 ECMAScript 函数对象 )、calleeContext (一个
执行上下文 )以及
thisArgument (一个 ECMAScript 语言值 ),并返回
unused 。它在调用时执行以下步骤:
1. 让 thisMode 为 F .[[ThisMode]] 。
2. 如果 thisMode 是 lexical ,则返回
unused 。
3. 让 calleeRealm 为 F .[[Realm]] 。
4. 让 localEnv 为 calleeContext 的词法环境。
5. 如果 thisMode 是 strict ,则:
a. 让 thisValue 为 thisArgument 。
6. 否则:
a. 如果 thisArgument 是 undefined 或
null ,则:
i. 让 globalEnv 为 calleeRealm .[[GlobalEnv]] 。
ii. Assert : globalEnv 是一个
全局环境记录 。
iii. 让 thisValue 为 globalEnv .[[GlobalThisValue]] 。
b. 否则:
i. 让 thisValue 为 ! ToObject (thisArgument )。
ii. 注意:ToObject 使用
calleeRealm 生成包装对象。
7. Assert : localEnv 是一个 函数环境记录 。
8. Assert : 下一步不会返回 突发完成 ,因为
localEnv .[[ThisBindingStatus]] 不是
initialized 。
9. 执行
! localEnv .BindThisValue(thisValue )。
10. 返回 unused 。
10.2.1.3 运行时语义:EvaluateBody
语法驱动操作 语法驱动操作
EvaluateBody 接受两个参数:functionObject (一个 ECMAScript 函数对象 )和
argumentsList (一个 列表 ,包含 ECMAScript 语言值 ),并返回一个
正常完成记录 ,
包含一个 ECMAScript 语言值 或者一个
突发完成记录 。它在以下产生式中被分段定义:
FunctionBody
: FunctionStatementList
1. 返回 ? EvaluateFunctionBody 的 FunctionBody ,参数为
functionObject 和 argumentsList 。
ConciseBody
: ExpressionBody
1. 返回 ? EvaluateConciseBody 的 ConciseBody ,参数为
functionObject 和 argumentsList 。
GeneratorBody
: FunctionBody
1. 返回 ? EvaluateGeneratorBody 的 GeneratorBody ,参数为
functionObject 和 argumentsList 。
AsyncGeneratorBody
: FunctionBody
1. 返回 ? EvaluateAsyncGeneratorBody 的 AsyncGeneratorBody ,参数为
functionObject 和 argumentsList 。
AsyncFunctionBody
: FunctionBody
1. 返回 ? EvaluateAsyncFunctionBody 的 AsyncFunctionBody ,参数为
functionObject 和 argumentsList 。
AsyncConciseBody
: ExpressionBody
1. 返回 ? EvaluateAsyncConciseBody 的 AsyncConciseBody ,参数为
functionObject 和 argumentsList 。
Initializer
:
=
AssignmentExpression
1. 断言 :argumentsList 为空。
2. 断言 :functionObject .[[ClassFieldInitializerName]] 不为空。
3. 如果 IsAnonymousFunctionDefinition (AssignmentExpression )
为 true ,则
a. 令 value 为 ? NamedEvaluation 的 Initializer ,参数为
functionObject .[[ClassFieldInitializerName]] 。
4. 否则,
a. 令 rhs 为 ? Evaluation 的 AssignmentExpression 。
b. 令 value 为 ? GetValue (rhs )。
5. 返回 完成记录 {
[[Type]] : return , [[Value]] :
value , [[Target]] :
empty }。
注
尽管字段初始化器构成函数边界,调用 FunctionDeclarationInstantiation
没有任何可观察的效果,因此被省略。
ClassStaticBlockBody
: ClassStaticBlockStatementList
1. 断言 :argumentsList 为空。
2. 返回 ? EvaluateClassStaticBlockBody 的 ClassStaticBlockBody
,参数为 functionObject 。
10.2.1.4 OrdinaryCallEvaluateBody ( F ,
argumentsList
)
抽象操作 OrdinaryCallEvaluateBody 接受两个参数:F (一个 ECMAScript 函数对象 )和
argumentsList (一个 列表 ,包含 ECMAScript 语言值 ),并返回一个
正常完成记录 ,
包含一个 ECMAScript 语言值 ,
或者一个 突发完成记录 。它在调用时执行以下步骤:
1. 返回 ? EvaluateBody 的 F .[[ECMAScriptCode]] ,参数为 F 和 argumentsList 。
10.2.2 [[Construct]] ( argumentsList ,
newTarget )
ECMAScript 函数对象 F 的 [[Construct]] 内部方法接受两个参数:argumentsList (一个 列表 ,包含 ECMAScript 语言值 )和
newTarget (一个 构造函数 ),并返回一个 正常完成记录 ,包含一个对象,或一个
抛出完成记录 。它在调用时执行以下步骤:
1. 令 callerContext 为当前 运行执行上下文 。
2. 令 kind 为 F .[[ConstructorKind]] 。
3. 如果 kind 为 base ,则
a. 令 thisArgument 为 ? OrdinaryCreateFromConstructor (newTarget ,
"%Object.prototype%" )。
4. 令 calleeContext 为 PrepareForOrdinaryCall (F ,
newTarget )。
5. Assert : calleeContext 现在是
运行执行上下文 。
6. 如果 kind 为 base ,则
a. 执行 OrdinaryCallBindThis (F ,
calleeContext , thisArgument )。
b. 令 initializeResult 为 Completion (InitializeInstanceElements (thisArgument ,
F ))。
c. 如果 initializeResult 是 突发完成记录 ,则
i. 从 执行上下文栈 中移除
calleeContext ,并将 callerContext 恢复为 运行执行上下文 。
ii. 返回 ? initializeResult 。
7. 令 constructorEnv 为 calleeContext 的
LexicalEnvironment。
8. 令 result 为 Completion (OrdinaryCallEvaluateBody (F ,
argumentsList ))。
9. 从 执行上下文栈 中移除
calleeContext ,并将 callerContext 恢复为 运行执行上下文 。
10. 如果 result 是 返回完成记录 ,则
a. 如果 result .[[Value]]
是一个对象 ,返回 result .[[Value]] 。
b. 如果 kind 为 base ,返回
thisArgument 。
c. 如果 result .[[Value]] 不是
undefined ,则抛出一个 TypeError 异常。
11. 否则,
a. ReturnIfAbrupt (result )。
12. 令 thisBinding 为
? constructorEnv .GetThisBinding()。
13. Assert : thisBinding 是一个对象 。
14. 返回 thisBinding 。
10.2.3 OrdinaryFunctionCreate ( functionPrototype ,
sourceText , ParameterList , Body , thisMode , env ,
privateEnv )
抽象操作 OrdinaryFunctionCreate 接受以下参数:functionPrototype (一个对象),
sourceText (一系列 Unicode 代码点),ParameterList (一个 解析节点 ),
Body (一个 解析节点 ),
thisMode (lexical-this 或 non-lexical-this ),
env (一个 环境记录 ),
和 privateEnv (一个 私有环境记录 或
null ),
并返回一个 ECMAScript 函数对象 。
它用于指定以默认的 [[Call]] 内部方法和无 [[Construct]] 内部方法(尽管可以通过像
MakeConstructor
这样的操作后续添加)的方式创建一个新函数。
sourceText 是要创建的函数的语法定义的源文本。调用时执行以下步骤:
1. 令 internalSlotsList 为 表
30 中列出的内部槽。
2. 令 F 为 OrdinaryObjectCreate (functionPrototype ,
internalSlotsList )。
3. 将 F .[[Call]] 设置为 10.2.1
中指定的定义。
4. 将 F .[[SourceText]] 设置为
sourceText 。
5. 将 F .[[FormalParameters]] 设置为
ParameterList 。
6. 将 F .[[ECMAScriptCode]] 设置为
Body 。
7. 如果 source text
matched by Body 是 严格模式代码 ,则令 Strict 为
true ;否则令 Strict 为 false 。
8. 将 F .[[Strict]] 设置为
Strict 。
9. 如果 thisMode 是 lexical-this ,则将
F .[[ThisMode]] 设置为 lexical 。
10. 否则如果 Strict 为 true ,则将
F .[[ThisMode]] 设置为 strict 。
11. 否则,将 F .[[ThisMode]] 设置为
global 。
12. 将 F .[[IsClassConstructor]] 设置为
false 。
13. 将 F .[[Environment]] 设置为
env 。
14. 将 F .[[PrivateEnvironment]] 设置为
privateEnv 。
15. 将 F .[[ScriptOrModule]] 设置为
GetActiveScriptOrModule ()。
16. 将 F .[[Realm]] 设置为 当前 Realm
记录 。
17. 将 F .[[HomeObject]] 设置为
undefined 。
18. 将 F .[[Fields]] 设置为一个新的空的
列表 。
19. 将 F .[[PrivateMethods]]
设置为一个新的空的 列表 。
20. 将 F .[[ClassFieldInitializerName]] 设置为 empty 。
21. 令 len 为 ParameterList
的期望参数数量。
22. 执行 SetFunctionLength (F ,
len )。
23. 返回 F 。
10.2.4 AddRestrictedFunctionProperties ( F , realm )
抽象操作 AddRestrictedFunctionProperties 接受两个参数:F (一个 函数对象 )
和 realm (一个 Realm 记录 ),并返回
unused 。
当调用时,它执行以下步骤:
1. 断言 : realm .[[Intrinsics]] .[[%ThrowTypeError% ]] 存在
并已初始化。
2. 令 thrower 为 realm .[[Intrinsics]] .[[%ThrowTypeError% ]]。
3. 执行 ! DefinePropertyOrThrow (F ,
"caller" , 属性描述符 { [[Get]] :
thrower , [[Set]] : thrower , [[Enumerable]] :
false , [[Configurable]] :
true }).
4. 执行 ! DefinePropertyOrThrow (F ,
"arguments" , 属性描述符 { [[Get]] :
thrower , [[Set]] : thrower , [[Enumerable]] : false , [[Configurable]] : true }).
5. 返回 unused 。
10.2.4.1 %ThrowTypeError% ( )
这个函数是 %ThrowTypeError% 内在对象。
它是一个匿名的内置 函数对象 ,在每个 Realm 中定义一次。
当调用时,它执行以下步骤:
1. 抛出一个 TypeError 异常。
这个函数的 [[Extensible]] 内部槽的值为
false 。
这个函数的 "length" 属性具有属性描述符 { [[Writable]] :
false , [[Enumerable]] :
false , [[Configurable]] : false }。
这个函数的 "name" 属性具有属性描述符 { [[Writable]] :
false , [[Enumerable]] :
false , [[Configurable]] : false }。
10.2.5 MakeConstructor ( F [ , writablePrototype [ ,
prototype ] ] )
抽象操作 MakeConstructor 接受一个参数 F (一个 ECMAScript 函数对象 或内置的 函数对象 ),以及可选参数
writablePrototype (一个布尔值)和 prototype (一个对象),并返回 unused 。
它将 F 转换为一个 构造函数 。当调用时,它执行以下步骤:
1. 如果 F 是一个 ECMAScript 函数对象 ,
则
a. 断言 : IsConstructor (F )
为 false 。
b. 断言 : F 是一个可扩展的对象,且没有一个名为
"prototype" 的自身属性。
c. 将 F .[[Construct]] 设置为
在 10.2.2
中指定的定义。
2. 否则,
a. 将 F .[[Construct]] 设置为
在 10.3.2
中指定的定义。
3. 将 F .[[ConstructorKind]] 设置为
base 。
4. 如果 writablePrototype 不存在,将 writablePrototype
设置为 true 。
5. 如果 prototype 不存在,则
a. 将 prototype 设置为 OrdinaryObjectCreate (%Object.prototype% )。
b. 执行 ! DefinePropertyOrThrow (prototype ,
"constructor" , 属性描述符 { [[Value]] :
F , [[Writable]] : writablePrototype , [[Enumerable]] : false , [[Configurable]] : true }).
6. 执行 ! DefinePropertyOrThrow (F ,
"prototype" , 属性描述符 { [[Value]] :
prototype , [[Writable]] : writablePrototype , [[Enumerable]] : false , [[Configurable]] : false }).
7. 返回 unused 。
10.2.6 MakeClassConstructor ( F )
抽象操作 MakeClassConstructor 接受一个参数 F (一个 ECMAScript 函数对象 ),并返回
unused 。当调用时,它执行以下步骤:
1. 断言 : F .[[IsClassConstructor]] 为 false 。
2. 将 F .[[IsClassConstructor]] 设置为
true 。
3. 返回 unused 。
10.2.7 MakeMethod ( F , homeObject )
抽象操作 MakeMethod 接受参数 F (一个 ECMAScript 函数对象 )和 homeObject (一个对象),并返回
unused 。
它将 F 配置为一个方法。当调用时,它执行以下步骤:
1. 将 F .[[HomeObject]] 设置为
homeObject 。
2. 返回 unused 。
10.2.8 DefineMethodProperty ( homeObject , key ,
closure , enumerable )
抽象操作 DefineMethodProperty 接受四个参数:homeObject (一个对象),key (一个 属性键 或 私有名称 ),closure (一个 函数对象 ),以及
enumerable (一个布尔值),并返回一个 正常完成记录 ,
其中包含一个 PrivateElement
或 unused ,或者是一个 突然完成 。
当调用时,它执行以下步骤:
1. 断言 : homeObject 是一个普通的、可扩展的对象。
2. 如果 key 是一个 私有名称 ,则
a. 返回 PrivateElement
{ [[Key]] : key , [[Kind]] :
method , [[Value]] : closure }。
3. 否则,
a. 让 desc 为 PropertyDescriptor { [[Value]] : closure , [[Writable]] :
true , [[Enumerable]] : enumerable , [[Configurable]] : true }。
b. 执行 ? DefinePropertyOrThrow (homeObject ,
key , desc )。
c. 注:DefinePropertyOrThrow
仅在尝试定义一个类静态方法时,如果 key 为 "prototype" ,才会返回 突然完成 。
d. 返回 unused 。
10.2.9 SetFunctionName ( F , name [ ,
prefix
]
)
抽象操作 SetFunctionName 接受两个必需参数和一个可选参数:F (一个 函数对象 )和
name (一个 属性键 或 私有名称 ),以及一个可选的
prefix (一个字符串),并返回
unused 。它将一个 "name" 属性添加到 F 上。它在调用时执行以下步骤:
1. 断言 : F 是一个可扩展的对象,并且没有
"name" 自有属性。
2. 如果 name 是一个符号 ,则
a. 让 description 为 name 的 [[Description]] 值。
b. 如果 description 为 undefined ,
将 name 设置为空字符串。
c. 否则,将 name 设置为 字符串连接 ,
包含 "[" 、description 和 "]" 。
3. 否则,如果 name 是一个 私有名称 ,则
a. 将 name 设置为 name 的 [[Description]] 。
4. 如果 F 有一个 [[InitialName]]
内部槽,则
a. 将 F .[[InitialName]]
设置为 name 。
5. 如果 prefix 存在,则
a. 将 name 设置为 字符串连接 ,
包含 prefix 、代码单元 0x0020(空格)和 name 。
b. 如果 F 有一个 [[InitialName]]
内部槽,则
i. 可选地,将 F .[[InitialName]]
设置为 name 。
6. 执行 ! DefinePropertyOrThrow (F ,
"name" ,属性描述符 { [[Value]] : name ,
[[Writable]] : false ,[[Enumerable]] :
false ,[[Configurable]] : true }).
7. 返回 unused 。
10.2.10 SetFunctionLength ( F , length )
抽象操作 SetFunctionLength 接受两个参数:F (一个 函数对象 )和
length (一个非负的 整数 或 +∞),并返回
unused 。它将一个 "length" 属性添加到 F 上。它在调用时执行以下步骤:
1. 断言 : F 是一个可扩展的对象,并且没有
"length" 自有属性。
2. 执行 ! DefinePropertyOrThrow (F ,
"length" ,属性描述符 { [[Value]] : 𝔽 (length ),
[[Writable]] : false ,[[Enumerable]] :
false ,[[Configurable]] : true }).
3. 返回 unused 。
10.2.11 FunctionDeclarationInstantiation ( func ,
argumentsList )
抽象操作 FunctionDeclarationInstantiation 接受两个参数:func (一个 ECMAScript 函数对象 )和
argumentsList (一个 列表 ,其中包含
ECMAScript 语言值 ),并返回一个
正常完成 包含
unused 或一个 突然完成 。func
是为其建立 执行上下文 的函数对象。
注 1
当为评估 ECMAScript 函数建立执行上下文时,会创建一个新的 函数环境记录 ,
并在该 环境记录 中实例化每个形式参数的绑定。
函数体中的每个声明也会被实例化。如果函数的形式参数没有包含任何默认值初始化器,则函数体中的声明会在与参数相同的
环境记录
中实例化。如果存在默认值参数初始化器,则为函数体声明创建第二个
环境记录 。形式参数和函数会在
FunctionDeclarationInstantiation 过程中初始化。所有其他绑定则在函数体评估期间初始化。
它在调用时执行以下步骤:
1. 让 calleeContext 是 正在执行的执行上下文 。
2. 让 code 是 func .[[ECMAScriptCode]] 。
3. 让 strict 是 func .[[Strict]] 。
4. 让 formals 是 func .[[FormalParameters]] 。
5. 让 parameterNames 是 绑定名称
的
formals 。
6. 如果 parameterNames 有任何重复项,令
hasDuplicates 为 true 。否则,令 hasDuplicates 为
false 。
7. 让 simpleParameterList 是 简单参数列表
的 formals 。
8. 让 hasParameterExpressions 是 包含表达式
的 formals 。
9. 让 varNames 是 变量声明名称
的 code 。
10. 让 varDeclarations 是 变量作用域声明
的 code 。
11. 让 lexicalNames 是 词法声明名称
的 code 。
12. 让 functionNames 是一个新的空的 列表 。
13. 让 functionsToInitialize 是一个新的空的 列表 。
14. 对于 varDeclarations 的每一个元素 d ,
按照反向 列表
顺序,执行以下操作
a. 如果 d 既不是 变量声明
也不是 ForBinding 也不是 BindingIdentifier ,则
i. 断言 : d 要么是
函数声明 ,
要么是 生成器声明 ,
要么是 异步函数声明 ,
要么是 异步生成器声明 。
ii. 让 fn 是 绑定名称
的唯一元素。
iii. 如果 functionNames 不包含
fn ,则
1. 将 fn 插入到 functionNames
的第一个位置。
2. 注: 如果有多个相同名称的函数声明,将使用最后一个声明。
3. 将 d 插入到 functionsToInitialize
的第一个位置。
15. 让 argumentsObjectNeeded 为 true 。
16. 如果 func .[[ThisMode]] 是
lexical ,则
a. 注: 箭头函数永远没有 arguments 对象。
b. 将 argumentsObjectNeeded 设置为
false 。
17. 否则,如果 parameterNames 包含
"arguments" ,则
a. 将 argumentsObjectNeeded 设置为
false 。
18. 否则,如果 hasParameterExpressions 为
false ,则
a. 如果 functionNames 包含
"arguments" 或 lexicalNames 包含
"arguments" ,则
i. 将 argumentsObjectNeeded 设置为
false 。
19. 如果 strict 为 true 或
hasParameterExpressions 为 false ,则
a. 注: 只需要一个 环境记录
来处理参数,因为在 eval
中的调用在 严格模式代码 中不能
创建在 eval
外部可见的新绑定。
b. 让 env 为 calleeContext 的
词法环境。
20. 否则,
a. 注: 需要一个单独的 环境记录
以确保由 直接
eval
调用在形式参数列表中创建的绑定在参数声明的环境之外。
b. 让 calleeEnv 为 calleeContext 的
词法环境。
c. 让 env 为 NewDeclarativeEnvironment (calleeEnv )。
d. 断言 : calleeContext 的变量环境是
calleeEnv 。
e. 将 calleeContext 的词法环境设置为
env 。
21. 对于 parameterNames 中的每个字符串 paramName ,执行
a. 让 alreadyDeclared 为
! env .HasBinding(paramName )。
b. 注: 早期错误 确保重复的参数名称只能出现在 非严格模式函数
中,并且这些函数没有参数默认值或剩余参数。
c. 如果 alreadyDeclared 为 false ,则
i. 执行
! env .CreateMutableBinding(paramName , false )。
ii. 如果 hasDuplicates 为 true ,则
1. 执行
! env .InitializeBinding(paramName , undefined )。
22. 如果 argumentsObjectNeeded 为 true ,则
a. 如果 strict 为 true 或
simpleParameterList 为 false ,则
i. 让 ao 为 CreateUnmappedArgumentsObject (argumentsList )。
b. 否则,
i. 注: 映射的参数对象仅在 非严格模式函数
中提供,并且这些函数没有剩余参数、参数默认值初始化器或任何解构参数。
ii. 让 ao 为 CreateMappedArgumentsObject (func ,
formals , argumentsList , env )。
c. 如果 strict 为 true ,则
i. 执行
! env .CreateImmutableBinding("arguments" ,
false )。
ii. 注: 在 严格模式代码
中,早期错误
防止尝试对该绑定进行赋值,因此其可变性不可观察。
d. 否则,
i. 执行
! env .CreateMutableBinding("arguments" ,
false )。
e. 执行
! env .InitializeBinding("arguments" , ao )。
f. 让 parameterBindings 为 list-concatenation 的
parameterNames 和 « "arguments" »。
23. 否则,
a. 让 parameterBindings 为
parameterNames 。
24. 让 iteratorRecord 为 CreateListIteratorRecord (argumentsList )。
25. 如果 hasDuplicates 为 true ,则
a. 执行 ? IteratorBindingInitialization 的 formals ,使用参数
iteratorRecord 和 undefined 。
26. 否则,
a. 执行 ? IteratorBindingInitialization 的 formals ,使用参数
iteratorRecord 和 env 。
27. 如果 hasParameterExpressions 为 false ,则
a. 注: 仅需要一个 环境记录
来处理参数和顶级变量。
b. 让 instantiatedVarNames 为
列表
parameterBindings 的副本。
c. 对于 varNames 中的每个元素 n ,执行
i. 如果 instantiatedVarNames 不包含 n ,则
1. 将 n 添加到 instantiatedVarNames 。
2. 执行
! env .CreateMutableBinding(n , false )。
3. 执行
! env .InitializeBinding(n , undefined )。
d. 让 varEnv 为 env 。
28. 否则,
a. 注: 需要一个单独的 环境记录
来确保在形式参数列表中创建的闭包无法访问函数体中的声明。
b. 让 varEnv 为 NewDeclarativeEnvironment (env )。
c. 将 calleeContext 的 VariableEnvironment 设置为
varEnv 。
d. 让 instantiatedVarNames 为一个新的空 列表 。
e. 对于 varNames 中的每个元素 n ,执行
i. 如果 instantiatedVarNames 不包含 n ,则
1. 将 n 添加到 instantiatedVarNames 。
2. 执行
! varEnv .CreateMutableBinding(n , false )。
3. 如果 parameterBindings 不包含 n ,或
functionNames 包含 n ,则
a. 让 initialValue 为
undefined 。
4. 否则,
a. 让 initialValue 为
! env .GetBindingValue(n , false )。
5. 执行
! varEnv .InitializeBinding(n , initialValue )。
6. 注: 与形式参数同名的变量最初具有与相应初始化参数相同的值。
29.
注: 附录 B.3.2.1
在此处添加了额外的步骤。
30. 如果 strict 为 false ,则
a. 让 lexEnv 为 NewDeclarativeEnvironment (varEnv )。
b. 注: 非严格模式函数
使用单独的 环境记录
处理顶级词法声明,以便 直接
eval 可以确定 eval 代码引入的任何 var 范围声明是否与已有的顶级词法范围声明冲突。对于 严格模式函数 不需要这样做,因为严格模式 直接
eval 总是将所有声明放入新的 环境记录 。
31. 否则,
a. 让 lexEnv 为 varEnv 。
32. 将 calleeContext 的 LexicalEnvironment 设置为
lexEnv 。
33. 让 lexDeclarations 为 词法作用域声明
的 code 。
34. 对于 lexDeclarations 中的每个元素 d ,执行
a. 注: 词法声明的名称不能与函数/生成器声明、形式参数或 var 名称相同。词法声明的名称仅在此处实例化,但不初始化。
b. 对于 d 的 绑定名称
中的每个元素 dn ,执行
i. 如果 是常量声明
的 d 为 true ,则
1. 执行
! lexEnv .CreateImmutableBinding(dn , true )。
ii. 否则,
1. 执行
! lexEnv .CreateMutableBinding(dn , false )。
35. 让 privateEnv 为 calleeContext 的
PrivateEnvironment。
36. 对于 functionsToInitialize 中的每个 解析节点
f ,执行
a. 让 fn 为 f 的 绑定名称
的唯一元素。
b. 让 fo 为 实例化函数对象
的 f ,参数为 lexEnv 和 privateEnv 。
c. 执行 ! varEnv .SetMutableBinding(fn ,
fo , false )。
37. 返回 unused 。
注 2
B.3.2
提供了上述算法的扩展,以确保与早于 ECMAScript 2015 的 web 浏览器实现的向后兼容性。
10.3 内置函数对象
内置的 函数对象 是一个 普通对象 ;它必须满足 普通对象 在 10.1
中规定的要求。
除了每个 普通对象 所需的内部插槽(见 10.1 ),内置的
函数对象 还必须具有以下内部插槽:
内置 函数对象 的 [[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 语言值 )或一个抛出完成记录。
1. 返回 ? BuiltinCallOrConstruct (F , thisArgument ,
argumentsList , undefined ).
10.3.2 [[Construct]] ( argumentsList ,
newTarget )
内置 函数对象
F 的 [[Construct]] 内部方法(当该方法存在时)接受参数 argumentsList (一个
列表 的 ECMAScript 语言值 )和
newTarget (一个 构造函数 ),并返回一个正常完成记录(包含一个对象)或一个抛出完成记录。
1. 返回 ? BuiltinCallOrConstruct (F ,
uninitialized , argumentsList , newTarget ).
10.3.3 BuiltinCallOrConstruct ( F , thisArgument ,
argumentsList , newTarget )
抽象操作 BuiltinCallOrConstruct 接受以下参数:F (一个内置的 函数对象 )、thisArgument (一个
ECMAScript 语言值 或
uninitialized )、argumentsList (一个 列表 的 ECMAScript 语言值 )、以及
newTarget (一个 构造函数 或
undefined )。它返回一个正常完成记录(包含一个 ECMAScript
语言值 )或一个抛出完成记录。调用时执行以下步骤:
1. 让 callerContext 为当前 运行中的执行上下文 。
2. 如果 callerContext 尚未被挂起,则挂起 callerContext 。
3. 让 calleeContext 为一个新的 执行上下文 。
4. 将 calleeContext 的函数设置为 F 。
5. 让 calleeRealm 为 F .[[Realm]] 。
6. 将 calleeContext 的 Realm 设置为
calleeRealm 。
7. 将 calleeContext 的 ScriptOrModule 设置为
null 。
8. 执行对 calleeContext 的任何必要的 实现定义 初始化。
9. 将 calleeContext 推入 执行上下文栈 ;calleeContext
现在是 运行中的执行上下文 。
10. 让 result 为
完成记录 ,即以符合
F 规范的方式评估 F 的结果。如果 thisArgument 为
uninitialized ,则 this 的值为未初始化;否则,thisArgument 提供
this 值。argumentsList 提供命名参数。newTarget 提供 NewTarget 值。
11. 注:如果 F 在本文件中定义,“F 的规范”是通过算法步骤或其他方式指定的行为。
12. 从 执行上下文栈 中移除
calleeContext ,并将 callerContext 恢复为 运行中的执行上下文 。
13. 返回 ? result 。
Note
当 calleeContext 从 执行上下文栈
中移除时,如果它已经被挂起并被一个可访问的生成器保留以备后续恢复,则不得销毁。
10.3.4 CreateBuiltinFunction ( behaviour , length ,
name , additionalInternalSlotsList [ , realm [ , prototype [ ,
prefix ] ] ] )
抽象操作 CreateBuiltinFunction 接受以下参数:behaviour (一个 抽象闭包 、一组算法步骤,或本规范中定义的其他函数行为)、length (一个非负的
整数 或
+∞)、name (一个 属性键 或一个 私有名称 )、以及
additionalInternalSlotsList (一个 列表 ,包含内部槽的名称),和可选参数
realm (一个 Realm 记录 )、prototype (一个对象或
null ),以及 prefix (一个字符串)。该操作返回一个 函数对象 。additionalInternalSlotsList
包含必须作为对象的一部分定义的额外内部槽的名称。此操作创建一个内置的 函数对象 。它执行以下步骤:
1. 如果 realm 不存在,则将 realm 设置为 当前 Realm
记录 。
2. 如果 prototype 不存在,则将 prototype 设置为
realm .[[Intrinsics]] .[[%Function.prototype% ]]。
3. 让 internalSlotsList 为一个 列表 ,包含所有
10.3 对于即将创建的内置
函数对象 所需的内部槽的名称。
4. 将 additionalInternalSlotsList 的元素附加到
internalSlotsList 。
5. 让 func 为一个新的内置 函数对象 ,当调用时,它会根据
behaviour 的描述,使用提供的参数作为 behaviour 指定的相应参数的值。新的 函数对象 具有名称为
internalSlotsList 元素的内部槽,并具有一个 [[InitialName]] 内部槽。
6. 将 func .[[Prototype]] 设置为
prototype 。
7. 将 func .[[Extensible]] 设置为
true 。
8. 将 func .[[Realm]] 设置为
realm 。
9. 将 func .[[InitialName]] 设置为
null 。
10. 执行 SetFunctionLength (func ,
length )。
11. 如果 prefix 不存在,则
a. 执行 SetFunctionName (func ,
name )。
12. 否则,
a. 执行 SetFunctionName (func ,
name , prefix )。
13. 返回 func 。
本规范中定义的每个内置函数都是通过调用 CreateBuiltinFunction 抽象操作创建的。
10.4 内置的异域对象内部方法和槽
本规范定义了几种内置的 异域对象 。这些对象的行为通常类似于 普通对象 ,但在一些特定情况下有所不同。以下 异域对象
使用 普通对象 的内部方法,除非在下文中明确另有说明:
10.4.1 绑定函数异域对象
绑定函数异域对象 是一种 异域对象 ,它封装了另一个 函数对象 。一个 绑定函数异域对象 是可调用的(它有一个 [[Call]] 内部方法,并且可能有一个 [[Construct]] 内部方法)。调用一个 绑定函数异域对象 通常会调用它封装的函数。
一个对象是一个 绑定函数异域对象 ,如果它的 [[Call]] 和(如果适用的话)[[Construct]] 内部方法使用以下实现,并且它的其他基本内部方法使用在 10.1
中找到的定义。这些方法是在 BoundFunctionCreate 中安装的。
绑定函数异域对象 不具有 ECMAScript
函数对象 中列出的内部槽,这些槽在 表30
中列出。相反,它们具有 表31
中列出的内部槽,此外还有 [[Prototype]] 和 [[Extensible]] 。
表31:绑定函数异域对象的内部槽
内部槽
类型
描述
[[BoundTargetFunction]]
可调用的对象
封装的 函数对象 。
[[BoundThis]]
一个 ECMAScript 语言值
在调用封装的函数时始终传递的 this 值。
[[BoundArguments]]
一个 列表
的 ECMAScript 语言值
一个值的列表,其元素作为对封装函数的任何调用的第一个参数。
10.4.1.1 [[Call]] ( thisArgument ,
argumentsList )
[[Call]] 内部方法用于一个 绑定函数异域对象
F ,它接受参数 thisArgument (一个 ECMAScript
语言值 )和 argumentsList (一个 列表 的 ECMAScript 语言值 ),并返回一个包含
ECMAScript 语言值 的
正常完成记录 ,或者一个
抛出完成记录 。它在被调用时执行以下步骤:
1. 令 target 为 F .[[BoundTargetFunction]] 。
2. 令 boundThis 为 F .[[BoundThis]] 。
3. 令 boundArgs 为 F .[[BoundArguments]] 。
4. 令 args 为 列表连接 的
boundArgs 和 argumentsList 。
5. 返回 ? Call (target , boundThis , args )。
10.4.1.2 [[Construct]] ( argumentsList ,
newTarget )
[[Construct]] 内部方法用于一个 绑定函数异域对象
F ,它接受参数 argumentsList (一个 列表 的 ECMAScript 语言值 )和
newTarget (一个 构造函数 ),并返回一个包含 Object 的 正常完成记录 ,或者一个
抛出完成记录 。它在被调用时执行以下步骤:
1. 令 target 为 F .[[BoundTargetFunction]] 。
2. 断言 : IsConstructor (target )
为 true 。
3. 令 boundArgs 为 F .[[BoundArguments]] 。
4. 令 args 为 列表连接 的
boundArgs 和 argumentsList 。
5. 如果 SameValue (F ,
newTarget ) 为 true ,则将 newTarget 设置为 target 。
6. 返回 ? Construct (target , args ,
newTarget )。
10.4.1.3 BoundFunctionCreate ( targetFunction ,
boundThis , boundArgs )
抽象操作 BoundFunctionCreate 接受参数 targetFunction (一个 函数对象 )、boundThis (一个
ECMAScript 语言值 )和
boundArgs (一个 列表 的 ECMAScript
语言值 ),并返回一个包含函数对象的 正常完成记录 ,或者一个
抛出完成记录 。它用于指定创建新的
绑定函数异域对象 。它在被调用时执行以下步骤:
1. 令 proto 为 ? targetFunction .[[GetPrototypeOf]] ()。
2. 令 internalSlotsList 为 «[[Prototype]] ,[[Extensible]] » 和在 表
31 中列出的内部槽的 列表连接 。
3. 令 obj 为 MakeBasicObject (internalSlotsList )。
4. 将 obj .[[Prototype]] 设置为
proto 。
5. 将 obj .[[Call]] 设置为在 10.4.1.1
中描述的内容。
6. 如果 IsConstructor (targetFunction )
为 true ,则:
a. 将 obj .[[Construct]] 设置为在
10.4.1.2
中描述的内容。
7. 将 obj .[[BoundTargetFunction]]
设置为 targetFunction 。
8. 将 obj .[[BoundThis]] 设置为
boundThis 。
9. 将 obj .[[BoundArguments]] 设置为
boundArgs 。
10. 返回 obj 。
10.4.2 数组异域对象
数组是一个 异域对象 ,它对 数组索引 属性键 给予特殊处理(见 6.1.7 )。一个属性的 属性名
是一个 数组索引 时,这个属性也被称为 元素 。每个数组都有一个不可配置的
"length" 属性,其值始终是一个非负的 整数 ,其 数学值 严格小于 2** 32 。"length" 属性的值在数值上大于每个其名称为 数组索引
的自身属性的名称;每当创建或改变数组的自身属性时,会根据需要调整其他属性以保持这一不变性。具体来说,每当添加一个名称为 数组索引 的自身属性时,"length"
属性的值会被必要地更改为比该 数组索引 的数值大 1;并且每当 "length"
属性的值被更改时,每个其名称为 数组索引
的自身属性,其值不小于新长度时都会被删除。这一约束仅适用于数组的自身属性,不受可能从其原型继承的 "length" 或 数组索引 属性的影响。
一个对象是一个 数组异域对象 (或简称为数组),如果它的 [[DefineOwnProperty]]
内部方法使用以下实现,并且它的其他基本内部方法使用在 10.1
中找到的定义。这些方法被安装在 ArrayCreate 中。
10.4.2.1 [[DefineOwnProperty]] ( P ,
Desc )
[[DefineOwnProperty]] 内部方法在 数组
异域对象 A 中接受参数 P (一个 属性键 )和 Desc
(一个 属性描述符 ),并返回
一个 正常完成记录 ,其中包含
一个布尔值或一个 抛出完成记录 。调用时,它
执行以下步骤:
1. 如果 P 是 "length" ,则
a. 返回 ? ArraySetLength (A ,
Desc ).
2. 否则,如果 P 是一个 数组索引 ,则
a. 让 lengthDesc 为 OrdinaryGetOwnProperty (A ,
"length" ).
b. Assert : IsDataDescriptor (lengthDesc )
是
true 。
c. Assert : lengthDesc .[[Configurable]]
是 false 。
d. 让 length 为 lengthDesc .[[Value]] 。
e. Assert : length 是一个非负的
整数 。
f. 让 index 为 ! ToUint32 (P )。
g. 如果 index ≥ length 且
lengthDesc .[[Writable]] 是
false ,则返回 false 。
h. 让 succeeded 为 ! OrdinaryDefineOwnProperty (A ,
P , Desc )。
i. 如果 succeeded 是 false ,则返回
false 。
j. 如果 index ≥ length ,则
i. 将 lengthDesc .[[Value]] 设置为 index + 1 𝔽 。
ii. 将 succeeded 设置为 ! OrdinaryDefineOwnProperty (A ,
"length" , lengthDesc )。
iii. Assert : succeeded 是
true 。
k. 返回 true 。
3. 返回 ? OrdinaryDefineOwnProperty (A , P ,
Desc )。
10.4.2.2 ArrayCreate ( length [ , proto ] )
抽象操作 ArrayCreate 接受参数 length (一个非负的 整数 )
和一个可选参数 proto (一个对象),并返回一个 正常完成记录 ,其中包含
一个 数组异域对象
或一个 抛出完成记录 。它用于指定创建新的数组。调用时,它执行以下步骤:
1. 如果 length > 2** 32 - 1,抛出一个 RangeError 异常。
2. 如果 proto 不存在,将 proto 设置为 %Array.prototype% 。
3. 让 A 为 MakeBasicObject (« [[Prototype]] , [[Extensible]] »)。
4. 将 A .[[Prototype]] 设置为
proto 。
5. 将 A .[[DefineOwnProperty]]
设置为在 10.4.2.1
中规定的方式。
6. 执行 ! OrdinaryDefineOwnProperty (A ,
"length" , 属性描述符 { [[Value]] : 𝔽 (length ), [[Writable]] : true ,
[[Enumerable]] : false , [[Configurable]] : false })。
7. 返回 A 。
10.4.2.3 ArraySpeciesCreate ( originalArray , length )
抽象操作 ArraySpeciesCreate 接受两个参数:originalArray (一个对象)和 length (一个非负的 整数 ),并返回一个对象,可能是 正常完成记录 ,也可能是一个
抛出完成记录 。它用于指定使用从
originalArray 派生的 构造函数 创建一个新的数组或类似对象。它并不强制 构造函数
函数返回一个数组。调用时,它执行以下步骤:
1. 让 isArray 为 ? IsArray (originalArray )。
2. 如果 isArray 为 false ,返回
? ArrayCreate (length )。
3. 让 C 为 ? Get (originalArray ,
"constructor" )。
4. 如果 IsConstructor (C ) 为
true ,则
a. 让 thisRealm 为 当前 Realm 记录 。
b. 让 realmC 为 ? GetFunctionRealm (C )。
c. 如果 thisRealm 和 realmC 不是同一个 Realm
记录 ,则
i. 如果 SameValue (C ,
realmC .[[Intrinsics]] .[[%Array% ]]) 为
true ,则将 C 设置为 undefined 。
5. 如果 C 是一个对象 ,则
a. 将 C 设置为 ? Get (C , @@species )。
b. 如果 C 为 null ,将 C 设置为
undefined 。
6. 如果 C 为 undefined ,返回
? ArrayCreate (length )。
7. 如果 IsConstructor (C ) 为
false ,抛出一个 TypeError 异常。
8. 返回 ? Construct (C , « 𝔽 (length ) »)。
注
如果 originalArray 是使用标准内置 Array 构造函数 创建的,并且它的 Realm 与 运行时执行上下文 的
Realm
不同,则在 运行时执行上下文 的 Realm 中创建一个新的
Array。这保持了与历史上在使用 ArraySpeciesCreate 定义的 Array.prototype 方法时的浏览器兼容性。
10.4.2.4 ArraySetLength ( A , Desc )
抽象操作 ArraySetLength 接受两个参数:A (一个数组)和 Desc (一个
属性描述符 ),并返回一个
正常完成记录 ,包含一个布尔值,或者一个
抛出完成记录 。调用时,它执行以下步骤:
1. 如果 Desc 没有 [[Value]] 字段,则
a. 返回 ! OrdinaryDefineOwnProperty (A ,
"length" , Desc ).
2. 让 newLenDesc 为 Desc 的一个副本。
3. 让 newLen 为
? ToUint32 (Desc .[[Value]] )。
4. 让 numberLen 为
? ToNumber (Desc .[[Value]] )。
5. 如果 SameValueZero (newLen ,
numberLen ) 为 false ,则抛出一个 RangeError 异常。
6. 将 newLenDesc .[[Value]] 设置为
newLen 。
7. 让 oldLenDesc 为 ? OrdinaryGetOwnProperty (A ,
"length" )。
8. Assert :IsDataDescriptor (oldLenDesc )
为 true 。
9. Assert :oldLenDesc .[[Configurable]] 为 false 。
10. 让 oldLen 为 oldLenDesc .[[Value]] 。
11. 如果 newLen ≥ oldLen ,则
a. 返回 ! OrdinaryDefineOwnProperty (A ,
"length" , newLenDesc ).
12. 如果 oldLenDesc .[[Writable]] 为
false ,返回 false 。
13. 如果 newLenDesc 没有 [[Writable]] 字段,或者 newLenDesc .[[Writable]] 为
true ,则
a. 让 newWritable 为 true 。
14. 否则,
a. 注意:将 [[Writable]] 属性设置为
false 是延迟的,以防某些元素无法被删除。
b. 让 newWritable 为 false 。
c. 将 newLenDesc .[[Writable]]
设置为 true 。
15. 让 succeeded 为 ! OrdinaryDefineOwnProperty (A ,
"length" , newLenDesc )。
16. 如果 succeeded 为 false ,则返回
false 。
17. 对于 A 中每个拥有的 属性键
P ,其中 P 是一个 数组索引 ,并且 ! ToUint32 (P ) ≥
newLen ,按降序数字索引顺序,执行
a. 让 deleteSucceeded 为 ! A .[[Delete]] (P )。
b. 如果 deleteSucceeded 为 false ,则
i. 将 newLenDesc .[[Value]] 设置为 ! ToUint32 (P ) +
1 𝔽 。
ii. 如果 newWritable 为 false ,则将
newLenDesc .[[Writable]] 设置为 false 。
iii. 执行 ! OrdinaryDefineOwnProperty (A ,
"length" , newLenDesc )。
iv. 返回 false 。
18. 如果 newWritable 为 false ,则
a. 将 succeeded 设置为 ! OrdinaryDefineOwnProperty (A ,
"length" , 属性描述符 { [[Writable]] :false } )。
b. Assert :succeeded 为
true 。
19. 返回 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 。它在被调用时执行以下步骤:
1. 让 desc 为 OrdinaryGetOwnProperty (S ,
P ).
2. 如果 desc 不为 undefined ,则返回
desc 。
3. 返回 StringGetOwnProperty (S ,
P ).
10.4.3.2 [[DefineOwnProperty]] ( P ,
Desc )
一个 字符串异域对象 S 的 [[DefineOwnProperty]] 内部方法接收两个参数:P (一个 属性键 )和
Desc (一个 属性描述符 ),并返回一个
正常完成 ,其中包含一个布尔值。它在被调用时执行以下步骤:
1. 让 stringDesc 为 StringGetOwnProperty (S ,
P ).
2. 如果 stringDesc 不为 undefined ,则:
a. 让 extensible 为 S .[[Extensible]] 。
b. 返回 IsCompatiblePropertyDescriptor (extensible ,
Desc , stringDesc ).
3. 返回 ! OrdinaryDefineOwnProperty (S ,
P , Desc ).
10.4.3.3 [[OwnPropertyKeys]] ( )
一个 字符串异域对象 O 的 [[OwnPropertyKeys]] 内部方法不接受任何参数,并返回一个 正常完成 ,其中包含一个
属性键列表 。它在被调用时执行以下步骤:
1. 让 keys 为一个新的空 列表 。
2. 让 str 为 O .[[StringData]] 。
3. 断言 : str 是一个字符串 。
4. 让 len 为 str 的长度。
5. 对每一个整数 i ,使得 0 ≤ i
< len ,按升序执行:
a. 将 ! ToString (𝔽 (i )) 追加到
keys 。
6. 对 O 的每一个自有属性键 P ,使得 P 是一个
数组索引 并且 ! ToIntegerOrInfinity (P )
≥ len ,按升序的数字索引顺序执行:
a. 将 P 追加到 keys 。
7. 对 O 的每一个自有属性键 P ,使得 P 是一个
字符串 并且
P 不是一个 数组索引 ,按属性创建的时间顺序执行:
a. 将 P 追加到 keys 。
8. 对 O 的每一个自有属性键 P ,使得 P 是一个
符号 ,按属性创建的时间顺序执行:
a. 将 P 追加到 keys 。
9. 返回 keys 。
10.4.3.4 StringCreate ( value , prototype )
抽象操作 StringCreate 接受两个参数:value (一个字符串)和 prototype (一个对象),并返回一个 字符串异域对象 。它用于指定新 字符串异域对象 的创建。它在调用时执行以下步骤:
1. 让 S 为 MakeBasicObject (« [[Prototype]] , [[Extensible]] , [[StringData]] »)。
2. 将 S .[[Prototype]] 设置为
prototype 。
3. 将 S .[[StringData]] 设置为
value 。
4. 将 S .[[GetOwnProperty]] 设置为
10.4.3.1
中指定的内容。
5. 将 S .[[DefineOwnProperty]] 设置为
10.4.3.2
中指定的内容。
6. 将 S .[[OwnPropertyKeys]] 设置为
10.4.3.3
中指定的内容。
7. 让 length 为 value 的长度。
8. 执行 ! DefinePropertyOrThrow (S ,
"length" , 属性描述符 { [[Value]] : 𝔽 (length ), [[Writable]] : false , [[Enumerable]] :
false , [[Configurable]] : false })。
9. 返回 S 。
10.4.3.5 StringGetOwnProperty ( S , P )
抽象操作 StringGetOwnProperty 接受两个参数:S (一个具有 [[StringData]] 内部槽的对象)和
P (一个 属性键 ),并返回一个 属性描述符 或
undefined 。它在调用时执行以下步骤:
1. 如果 P 不是一个字符串 ,返回
undefined 。
2. 让 index 为 CanonicalNumericIndexString (P )。
3. 如果 index 是 undefined ,返回
undefined 。
4. 如果 IsIntegralNumber (index )
是 false ,返回 undefined 。
5. 如果 index 是 -0 𝔽 ,返回
undefined 。
6. 让 str 为 S .[[StringData]] 。
7. Assert : str 是一个字符串 。
8. 让 len 为 str 的长度。
9. 如果 ℝ (index ) < 0 或 len
≤ ℝ (index ),返回
undefined 。
10. 让 resultStr 为 str 从 ℝ (index ) 到
ℝ (index ) + 1 的子字符串。
11. 返回属性描述符 { [[Value]] :
resultStr , [[Writable]] : false , [[Enumerable]] : true , [[Configurable]] : false }。
10.4.4 Arguments Exotic Objects
大多数 ECMAScript 函数会向其代码提供一个 arguments 对象。根据函数定义的特性,其 arguments 对象可能是一个 普通对象 或
arguments
特殊对象 。一个 arguments 特殊对象 是一种 特殊对象 ,其
数组索引
属性映射到其关联 ECMAScript 函数的正式参数绑定。
如果一个对象的内部方法使用以下实现(未在此处指定的使用 10.1
中找到的实现),则该对象是一个 arguments 特殊对象 。这些方法由 CreateMappedArgumentsObject
安装。
Note 1
Arguments 特殊对象
具有与 普通对象 相同的内部槽。它们还具有一个 [[ParameterMap]] 内部槽。普通 arguments 对象也具有一个 [[ParameterMap]]
内部槽,其值始终为 undefined。对于普通 arguments 对象,[[ParameterMap]] 内部槽仅由
Object.prototype.toString
(20.1.3.6 ) 用于识别它们。
Note 2
一个 整数索引 数据属性
的 arguments 特殊对象 的数字名称值小于
相应 函数对象
的正式参数数量时,初始时它们的值与函数的 执行上下文 中相应的参数绑定共享。这
意味着,改变属性会改变相应的参数绑定的值,反之亦然。如果删除该属性后重新定义它,或者如果该属性被改变为 存取属性 ,则这种对应关系会中断。如果 arguments 对象是一个
普通对象 ,则其属性的值仅是传递给函数的参数的副本,属性值与正式参数值之间没有动态关联。
Note 3
ParameterMap 对象及其属性值用作指定 arguments 对象与参数绑定之间对应关系的设备。ParameterMap 对象及其属性值并不直接从 ECMAScript
代码中可观察。ECMAScript 实现不需要实际创建或使用此类对象来实现指定的语义。
Note 4
普通 arguments 对象定义了一个不可配置的 存取属性 ,其名称为
"callee" ,在访问时会抛出 TypeError 异常。对于 arguments
特殊对象 ,"callee" 属性具有更具体的意义,这些对象仅为某些 非严格模式函数 创建。普通变体中的该属性定义存在是为了确保符合
ECMAScript 规范的实现不会以其他方式定义该属性。
Note 5
ECMAScript 对 arguments 特殊对象 的实现历史上包含了一个名为
"caller" 的 存取属性 。在 ECMAScript 2017 之前,规范中包括了在普通
arguments 对象上定义一个抛出异常的 "caller" 属性。由于实现不再包含此扩展,ECMAScript 2017 删除了对抛出异常的
"caller" 存取器的要求。
10.4.4.1 [[GetOwnProperty]] ( P )
[[GetOwnProperty]] 内部方法用于 arguments
特殊对象 args ,接受一个参数 P (一个 属性键 ),并
返回一个 正常完成记录 ,该记录包含
一个 属性描述符 或
undefined 。当调用时,它执行以下步骤:
1. 令 desc 为 OrdinaryGetOwnProperty (args ,
P )。
2. 如果 desc 为 undefined ,则返回
undefined 。
3. 令 map 为 args .[[ParameterMap]] 。
4. 令 isMapped 为 ! HasOwnProperty (map ,
P )。
5. 如果 isMapped 为 true ,则
a. 将 desc .[[Value]] 设置为
! Get (map ,
P )。
6. 返回 desc 。
10.4.4.2 [[DefineOwnProperty]] ( P ,
Desc )
[[DefineOwnProperty]] 内部方法用于 arguments
特殊对象 args ,接受两个参数:P (一个 属性键 )和
Desc (一个 属性描述符 ),并
返回一个 正常完成记录 ,该记录
包含一个布尔值。调用时,它执行以下步骤:
1. 令 map 为 args .[[ParameterMap]] 。
2. 令 isMapped 为 ! HasOwnProperty (map ,
P )。
3. 令 newArgDesc 为 Desc 。
4. 如果 isMapped 为 true 且
IsDataDescriptor (Desc )
为 true ,则
a. 如果 Desc 没有 [[Value]]
字段,Desc 有一个
[[Writable]] 字段,且 Desc .[[Writable]] 为
false ,则
i. 将 newArgDesc 设置为 Desc 的副本。
ii. 将 newArgDesc .[[Value]] 设置为
! Get (map ,
P )。
5. 令 allowed 为 ! OrdinaryDefineOwnProperty (args ,
P , newArgDesc )。
6. 如果 allowed 为 false ,则返回
false 。
7. 如果 isMapped 为 true ,则
a. 如果 IsAccessorDescriptor (Desc )
为 true ,则
i. 执行 ! map .[[Delete]] (P )。
b. 否则,
i. 如果 Desc 有 [[Value]]
字段,则
1. Assert : 以下 Set 操作将成功,因为由
arguments 对象映射的正式参数始终是可写的。
2. 执行 ! Set (map ,
P , Desc .[[Value]] ,
false )。
ii. 如果 Desc 有 [[Writable]] 字段且
Desc .[[Writable]] 为 false ,则
1. 执行 ! map .[[Delete]] (P )。
8. 返回 true 。
10.4.4.3 [[Get]] ( P ,
Receiver )
[[Get]] 内部方法用于 arguments 特殊对象
args ,接受两个参数:
P (一个 属性键 )
和 Receiver (一个 ECMAScript 语言值 ),并返回一个正常
完成记录,其中包含一个 ECMAScript 语言值 或一个
抛出完成 。调用时,它执行以下步骤:
1. 令 map 为 args .[[ParameterMap]] 。
2. 令 isMapped 为 ! HasOwnProperty (map ,
P )。
3. 如果 isMapped 为 false ,则
a. 返回 ? OrdinaryGet (args ,
P , Receiver )。
4. 否则,
a. Assert :
map 包含 P 的正式参数映射。
b. 返回 ! Get (map , P )。
10.4.4.4 [[Set]] ( P , V ,
Receiver )
[[Set]] 内部方法用于 arguments 特殊对象
args ,接受三个参数:
P (一个 属性键 ),
V (一个 ECMAScript 语言值 ),
和 Receiver (一个 ECMAScript 语言值 ),并返回一个正常
完成记录,其中包含一个布尔值或一个 抛出完成 。调用时,它执行以下步骤:
1. 如果 SameValue (args ,
Receiver ) 为 false ,则
a. 令 isMapped 为 false 。
2. 否则,
a. 令 map 为 args .[[ParameterMap]] 。
b. 令 isMapped 为 ! HasOwnProperty (map ,
P )。
3. 如果 isMapped 为 true ,则
a. Assert :以下的 Set 操作将会成功,因为 arguments
对象中的正式参数总是可写的。
b. 执行 ! Set (map ,
P , V , false )。
4. 返回 ? OrdinarySet (args , P , V ,
Receiver )。
10.4.4.5 [[Delete]] ( P )
[[Delete]] 内部方法用于 arguments 特殊对象
args ,
接受一个参数 P (一个 属性键 ),
并返回一个正常完成记录,其中包含一个布尔值或一个 抛出完成 。调用时,它执行以下步骤:
1. 令 map 为 args .[[ParameterMap]] 。
2. 令 isMapped 为 ! HasOwnProperty (map ,
P )。
3. 令 result 为 ? OrdinaryDelete (args , P )。
4. 如果 result 为 true 且
isMapped 为 true ,则
a. 执行 ! map .[[Delete]] (P )。
5. 返回 result 。
10.4.4.6 CreateUnmappedArgumentsObject ( argumentsList )
抽象操作 CreateUnmappedArgumentsObject 接受一个参数 argumentsList (一个 列表 ,包含 ECMAScript 语言值 ),并返回一个
普通对象 。调用时,它执行以下步骤:
1. 令 len 为 argumentsList 中的元素数量。
2. 令 obj 为 OrdinaryObjectCreate (%Object.prototype% ,
« [[ParameterMap]] »).
3. 将 obj .[[ParameterMap]] 设置为
undefined 。
4. 执行 ! DefinePropertyOrThrow (obj ,
"length" , 属性描述符 { [[Value]] : 𝔽 (len ),
[[Writable]] : true ,
[[Enumerable]] : false , [[Configurable]] : true }).
5. 令 index 为 0。
6. 重复,直到 index < len ,
a. 令 val 为
argumentsList [index ]。
b. 执行 ! CreateDataPropertyOrThrow (obj ,
! ToString (𝔽 (index )),
val )。
c. 将 index 设置为 index + 1。
7. 执行 ! DefinePropertyOrThrow (obj ,
@@iterator ,
属性描述符 { [[Value]] : %Array.prototype.values%, [[Writable]] : true ,
[[Enumerable]] : false , [[Configurable]] : true }).
8. 执行 ! DefinePropertyOrThrow (obj ,
"callee" , 属性描述符 { [[Get]] : %ThrowTypeError% , [[Set]] : %ThrowTypeError% , [[Enumerable]] : false ,
[[Configurable]] : false }).
9. 返回 obj 。
10.4.4.7 CreateMappedArgumentsObject ( func , formals ,
argumentsList , env )
抽象操作 CreateMappedArgumentsObject 接受参数 func (一个对象)、formals (一个 解析节点 )、argumentsList (一个
列表 ,包含 ECMAScript 语言值 )和
env (一个 环境记录 ),并返回一个 arguments 特殊对象 。调用时执行以下步骤:
1. 断言 :formals
不包含剩余参数、任何绑定模式或任何初始化器。它可以包含重复的标识符。
2. 令 len 为 argumentsList 中元素的数量。
3. 令 obj 为 MakeBasicObject (« [[Prototype]] , [[Extensible]] , [[ParameterMap]] »)。
4. 设置 obj .[[GetOwnProperty]] 如
10.4.4.1
所述。
5. 设置 obj .[[DefineOwnProperty]]
如 10.4.4.2
所述。
6. 设置 obj .[[Get]] 如 10.4.4.3
所述。
7. 设置 obj .[[Set]] 如 10.4.4.4
所述。
8. 设置 obj .[[Delete]] 如 10.4.4.5 所述。
9. 设置 obj .[[Prototype]] 为
%Object.prototype% 。
10. 令 map 为 OrdinaryObjectCreate (null )。
11. 设置 obj .[[ParameterMap]] 为
map 。
12. 令 parameterNames 为 BoundNames 的
formals 。
13. 令 numberOfParameters 为 parameterNames
中元素的数量。
14. 令 index 为 0。
15. 重复,直到 index < len ,
a. 令 val 为
argumentsList [index ]。
b. 执行 ! CreateDataPropertyOrThrow (obj ,
! ToString (𝔽 (index )),
val )。
c. 设置 index 为 index + 1。
16. 执行 ! DefinePropertyOrThrow (obj ,
"length" , PropertyDescriptor { [[Value]] : 𝔽 (len ), [[Writable]] : true , [[Enumerable]] :
false , [[Configurable]] : true })。
17. 令 mappedNames 为一个新的空的 列表 。
18. 设置 index 为 numberOfParameters - 1。
19. 重复,直到 index ≥ 0,
a. 令 name 为
parameterNames [index ]。
b. 如果 mappedNames 不包含 name ,那么
i. 将 name 添加到 mappedNames 。
ii. 如果 index < len ,那么
1. 令 g 为 MakeArgGetter (name ,
env )。
2. 令 p 为 MakeArgSetter (name ,
env )。
3. 执行 ! map .[[DefineOwnProperty]] (! ToString (𝔽 (index )),
PropertyDescriptor { [[Set]] : p , [[Get]] : g , [[Enumerable]] :
false , [[Configurable]] :
true })。
c. 设置 index 为 index - 1。
20. 执行 ! DefinePropertyOrThrow (obj ,
@@iterator ,
PropertyDescriptor { [[Value]] : %Array.prototype.values%, [[Writable]] : true , [[Enumerable]] :
false , [[Configurable]] : true })。
21. 执行 ! DefinePropertyOrThrow (obj ,
"callee" , PropertyDescriptor { [[Value]] : func ,
[[Writable]] : true , [[Enumerable]] : false , [[Configurable]] : true })。
22. 返回 obj 。
10.4.4.7.1 MakeArgGetter ( name , env )
抽象操作 MakeArgGetter 接受参数 name (一个字符串)和 env (一个 环境记录 ),并返回一个 函数对象 。它创建一个内置的 函数对象 ,该函数对象在执行时返回在 env 中绑定的
name 的值。调用时执行以下步骤:
1. 令 getterClosure 为一个新的 抽象闭包 ,无参数,捕获 name 和
env ,并在调用时执行以下步骤:
a. 返回 env .GetBindingValue(name ,
false )。
2. 令 getter 为 CreateBuiltinFunction (getterClosure ,
0, "" , « »)。
3. 注意:getter 从不直接被 ECMAScript 代码访问。
4. 返回 getter 。
10.4.4.7.2 MakeArgSetter ( name , env )
抽象操作 MakeArgSetter 接受参数 name (一个字符串)和 env (一个 环境记录 ),并返回一个 函数对象 。它创建一个内置的 函数对象 ,该函数对象在执行时设置在 env 中绑定的
name 的值。调用时执行以下步骤:
1. 令 setterClosure 为一个新的 抽象闭包 ,参数为
(value ),捕获 name 和 env ,并在调用时执行以下步骤:
a. 返回 ! env .SetMutableBinding(name ,
value , false )。
2. 令 setter 为 CreateBuiltinFunction (setterClosure ,
1, "" , « »)。
3. 注意:setter 从不直接被 ECMAScript 代码访问。
4. 返回 setter 。
10.4.5 TypedArray 特殊对象
TypedArray 是一种 特殊对象 ,它对 整数索引 属性键 进行特殊处理。
TypedArrays 具有与 普通对象 相同的内部槽,并且额外具有 [[ViewedArrayBuffer]] 、[[ArrayLength]] 、[[ByteOffset]] 、[[ContentType]] 和 [[TypedArrayName]] 内部槽。
如果一个对象的 [[GetOwnProperty]] 、[[HasProperty]] 、[[DefineOwnProperty]] 、[[Get]] 、[[Set]] 、[[Delete]] 和 [[OwnPropertyKeys]] 内部方法使用本节中的定义,并且其其他基本内部方法使用 10.1
中的定义,则该对象是一个 TypedArray 。这些方法由 TypedArrayCreate 安装。
10.4.5.1 [[GetOwnProperty]] ( P )
[[GetOwnProperty]] 是 TypedArray O 的内部方法,它接受参数
P (一个 属性键 ),并返回一个 正常完成记录 ,包含
属性描述符 或
undefined 。调用时执行以下步骤:
1. 如果 P 是一个字符串 ,则:
a. 令 numericIndex 为 CanonicalNumericIndexString (P )。
b. 如果 numericIndex 不是 undefined ,则:
i. 令 value 为 TypedArrayGetElement (O ,
numericIndex )。
ii. 如果 value 是 undefined ,则返回
undefined 。
iii. 返回属性描述符 { [[Value]] :
value , [[Writable]] : true , [[Enumerable]] : true , [[Configurable]] : true }。
2. 返回 OrdinaryGetOwnProperty (O ,
P )。
10.4.5.2 [[HasProperty]] ( P )
[[HasProperty]] 是 TypedArray O 的内部方法,它接受参数
P (一个 属性键 ),并返回一个 正常完成记录 ,包含一个布尔值或一个
抛出完成记录 。调用时执行以下步骤:
1. 如果 P 是一个字符串 ,则:
a. 令 numericIndex 为 CanonicalNumericIndexString (P )。
b. 如果 numericIndex 不是 undefined ,返回
IsValidIntegerIndex (O ,
numericIndex )。
2. 返回 ? OrdinaryHasProperty (O , P )。
10.4.5.3 [[DefineOwnProperty]] ( P ,
Desc )
[[DefineOwnProperty]] 是 TypedArray O 的内部方法,它接受参数
P (一个 属性键 )和 Desc (一个 属性描述符 ),并返回一个
正常完成记录 ,包含一个布尔值,或者一个
抛出完成记录 。调用时执行以下步骤:
1. 如果 P 是一个字符串 ,则:
a. 令 numericIndex 为 CanonicalNumericIndexString (P )。
b. 如果 numericIndex 不是 undefined ,则:
i. 如果 IsValidIntegerIndex (O ,
numericIndex ) 为 false ,则返回 false 。
ii. 如果 Desc 具有 [[Configurable]] 字段且 Desc .[[Configurable]] 为 false ,则返回
false 。
iii. 如果 Desc 具有 [[Enumerable]] 字段且 Desc .[[Enumerable]] 为 false ,则返回 false 。
iv. 如果 IsAccessorDescriptor (Desc )
为 true ,则返回 false 。
v. 如果 Desc 具有 [[Writable]]
字段且 Desc .[[Writable]] 为 false ,则返回
false 。
vi. 如果 Desc 具有 [[Value]]
字段,执行 ? TypedArraySetElement (O ,
numericIndex , Desc .[[Value]] )。
vii. 返回 true 。
2. 返回 ! OrdinaryDefineOwnProperty (O ,
P , Desc )。
10.4.5.4 [[Get]] ( P ,
Receiver )
[[Get]] 是 TypedArray O 的内部方法,它接受参数
P (一个 属性键 )和 Receiver (一个 ECMAScript 语言值 ),并返回一个
正常完成记录 ,包含一个
ECMAScript 语言值 或一个
抛出完成记录 。调用时执行以下步骤:
1. 如果 P 是一个字符串 ,则:
a. 令 numericIndex 为 CanonicalNumericIndexString (P )。
b. 如果 numericIndex 不是 undefined ,则:
i. 返回 TypedArrayGetElement (O ,
numericIndex )。
2. 返回 ? OrdinaryGet (O , P , Receiver )。
10.4.5.5 [[Set]] ( P , V ,
Receiver )
[[Set]] 是 TypedArray O 的内部方法,它接受参数
P (一个 属性键 )、V (一个 ECMAScript 语言值 )和
Receiver (一个 ECMAScript 语言值 ),并返回一个
正常完成记录 ,包含一个布尔值,或者一个
抛出完成记录 。调用时执行以下步骤:
1. 如果 P 是一个字符串 ,则:
a. 令 numericIndex 为 CanonicalNumericIndexString (P )。
b. 如果 numericIndex 不是 undefined ,则:
i. 如果 SameValue (O ,
Receiver ) 为 true ,则:
1. 执行 ? TypedArraySetElement (O ,
numericIndex , V )。
2. 返回 true 。
ii. 如果 IsValidIntegerIndex (O ,
numericIndex ) 为 false ,则返回 true 。
2. 返回 ? OrdinarySet (O , P , V ,
Receiver )。
10.4.5.6 [[Delete]] ( P )
[[Delete]] 是 TypedArray O 的内部方法,它接受参数
P (一个 属性键 ),并返回一个 正常完成记录 ,包含一个布尔值。调用时执行以下步骤:
1. 如果 P 是一个字符串 ,则:
a. 令 numericIndex 为 CanonicalNumericIndexString (P )。
b. 如果 numericIndex 不是 undefined ,则:
i. 如果 IsValidIntegerIndex (O ,
numericIndex ) 为 false ,则返回 true ;否则返回
false 。
2. 返回 ! OrdinaryDelete (O ,
P )。
10.4.5.7 [[OwnPropertyKeys]] ( )
[[OwnPropertyKeys]] 是 TypedArray O
的内部方法,它不接受任何参数,并返回一个 正常完成记录 ,包含一个
列表 ,其中包含
属性键 。调用时执行以下步骤:
1. 令 taRecord 为 MakeTypedArrayWithBufferWitnessRecord (O ,
seq-cst )。
2. 令 keys 为一个新的空的 列表 。
3. 如果 IsTypedArrayOutOfBounds (taRecord )
为 false ,则:
a. 令 length 为 TypedArrayLength (taRecord )。
b. 对于每个满足 0 ≤ i < length 的 整数
i ,按升序进行:
i. 将 ! ToString (𝔽 (i )) 添加到
keys 。
4. 对于每个 O 的自身 属性键
P ,如果 P 是一个字符串
并且 P 不是一个 整数索引 ,按属性创建的时间顺序升序进行:
a. 将 P 添加到 keys 。
5. 对于每个 O 的自身 属性键
P ,如果 P 是一个符号 ,按属性创建的时间顺序升序进行:
a. 将 P 添加到 keys 。
6. 返回 keys 。
10.4.5.8 带缓冲见证记录的 TypedArray
一个 带缓冲见证记录的 TypedArray 是一个
记录 值,用于封装一个
TypedArray 以及查看缓冲区的缓存字节长度。它用于确保当查看的缓冲区是一个
可增长的
SharedArrayBuffer 时,有一个单一的共享内存读取事件来读取字节长度数据块。
带缓冲见证记录的 TypedArray 具有 表
32 中列出的字段。
表 32: 带缓冲见证记录的
TypedArray 字段
字段名称
值
含义
[[Object]]
一个 TypedArray
其缓冲区的字节长度被加载的 TypedArray
[[CachedBufferByteLength]]
一个非负的 整数 或 detached
创建 记录
时对象的 [[ViewedArrayBuffer]] 的字节长度。
10.4.5.9 MakeTypedArrayWithBufferWitnessRecord ( obj ,
order )
抽象操作 MakeTypedArrayWithBufferWitnessRecord 接受参数 obj (一个 TypedArray )和
order (seq-cst 或 unordered ),并返回一个 带缓冲见证记录的
TypedArray 。调用时执行以下步骤:
1. 令 buffer 为 obj .[[ViewedArrayBuffer]] 。
2. 如果 IsDetachedBuffer (buffer )
为 true ,则:
a. 令 byteLength 为 detached 。
3. 否则,
a. 令 byteLength 为 ArrayBufferByteLength (buffer ,
order )。
4. 返回 带缓冲见证记录的
TypedArray { [[Object]] : obj , [[CachedBufferByteLength]] : byteLength }。
10.4.5.10 TypedArrayCreate ( prototype )
抽象操作 TypedArrayCreate 接受参数 prototype (一个对象),并返回一个 TypedArray 。它用于指定新 TypedArrays 的创建。调用时执行以下步骤:
1. 令 internalSlotsList 为 « [[Prototype]] , [[Extensible]] , [[ViewedArrayBuffer]] , [[TypedArrayName]] , [[ContentType]] , [[ByteLength]] , [[ByteOffset]] , [[ArrayLength]] »。
2. 令 A 为 MakeBasicObject (internalSlotsList )。
3. 设置 A .[[GetOwnProperty]] 如
10.4.5.1 中所指定的。
4. 设置 A .[[HasProperty]] 如
10.4.5.2 中所指定的。
5. 设置 A .[[DefineOwnProperty]] 如
10.4.5.3 中所指定的。
6. 设置 A .[[Get]] 如 10.4.5.4 中所指定的。
7. 设置 A .[[Set]] 如 10.4.5.5 中所指定的。
8. 设置 A .[[Delete]] 如 10.4.5.6 中所指定的。
9. 设置 A .[[OwnPropertyKeys]] 如
10.4.5.7 中所指定的。
10. 将 A .[[Prototype]] 设置为
prototype 。
11. 返回 A 。
10.4.5.11 TypedArrayByteLength ( taRecord )
抽象操作 TypedArrayByteLength 接受参数 taRecord (一个 带缓冲见证记录的
TypedArray ),并返回一个非负的 整数 。调用时执行以下步骤:
1. 如果 IsTypedArrayOutOfBounds (taRecord )
为 true ,则返回 0。
2. 令 length 为 TypedArrayLength (taRecord )。
3. 如果 length = 0,则返回 0。
4. 令 O 为 taRecord .[[Object]] 。
5. 如果 O .[[ByteLength]] 不为
auto ,则返回 O .[[ByteLength]] 。
6. 令 elementSize 为 TypedArrayElementSize (O )。
7. 返回 length × elementSize 。
10.4.5.12 TypedArrayLength ( taRecord )
抽象操作 TypedArrayLength 接受参数 taRecord (一个 带缓冲见证记录的
TypedArray ),并返回一个非负的 整数 。调用时执行以下步骤:
1. 断言 :IsTypedArrayOutOfBounds (taRecord )
为 false 。
2. 令 O 为 taRecord .[[Object]] 。
3. 如果 O .[[ArrayLength]] 不为
auto ,则返回 O .[[ArrayLength]] 。
4. 断言 :IsFixedLengthArrayBuffer (O .[[ViewedArrayBuffer]] ) 为 false 。
5. 令 byteOffset 为 O .[[ByteOffset]] 。
6. 令 elementSize 为 TypedArrayElementSize (O )。
7. 令 byteLength 为 taRecord .[[CachedBufferByteLength]] 。
8. 断言 :byteLength 不为
detached 。
9. 返回 floor ((byteLength -
byteOffset ) / elementSize )。
10.4.5.13 IsTypedArrayOutOfBounds ( taRecord )
抽象操作 IsTypedArrayOutOfBounds 接受参数 taRecord (一个 带缓冲见证记录的
TypedArray ),并返回一个布尔值。它检查对象的任何数值属性是否引用了基础缓冲区边界内不包含的索引处的值。调用时执行以下步骤:
1. 令 O 为 taRecord .[[Object]] 。
2. 令 bufferByteLength 为 taRecord .[[CachedBufferByteLength]] 。
3. 断言 :如果 O .[[ViewedArrayBuffer]] 为 IsDetachedBuffer ,则
bufferByteLength 必须为 detached 。
4. 如果 bufferByteLength 为 detached ,返回
true 。
5. 令 byteOffsetStart 为 O .[[ByteOffset]] 。
6. 如果 O .[[ArrayLength]] 为
auto ,则:
a. 令 byteOffsetEnd 为 bufferByteLength 。
7. 否则,
a. 令 elementSize 为 TypedArrayElementSize (O )。
b. 令 byteOffsetEnd 为 byteOffsetStart +
O .[[ArrayLength]] × elementSize 。
8. 如果 byteOffsetStart > bufferByteLength 或
byteOffsetEnd > bufferByteLength ,返回 true 。
9. 注意:长度为 0 的 TypedArrays 不被视为越界。
10. 返回 false 。
10.4.5.14 IsValidIntegerIndex ( O , index )
抽象操作 IsValidIntegerIndex 接受参数 O (一个 TypedArray )和
index (一个数字),并返回一个布尔值。调用时执行以下步骤:
1. 如果 IsDetachedBuffer (O .[[ViewedArrayBuffer]] ) 为 true ,返回 false 。
2. 如果 IsIntegralNumber (index )
为 false ,返回 false 。
3. 如果 index 是 -0 𝔽 ,返回
false 。
4. 令 taRecord 为 MakeTypedArrayWithBufferWitnessRecord (O ,
unordered )。
5. 注意:当 O 的后备缓冲区是一个 可增长的
SharedArrayBuffer 时,边界检查不是同步操作。
6. 如果 IsTypedArrayOutOfBounds (taRecord )
为 true ,返回 false 。
7. 令 length 为 TypedArrayLength (taRecord )。
8. 如果 ℝ (index ) < 0 或 ℝ (index ) ≥
length ,返回 false 。
9. 返回 true 。
10.4.5.15 TypedArrayGetElement ( O , index )
抽象操作 TypedArrayGetElement 接受参数 O (一个 TypedArray )和
index (一个数字),并返回一个数字、BigInt 或 undefined 。调用时执行以下步骤:
1. 如果 IsValidIntegerIndex (O ,
index ) 为 false ,返回 undefined 。
2. 令 offset 为 O .[[ByteOffset]] 。
3. 令 elementSize 为 TypedArrayElementSize (O )。
4. 令 byteIndexInBuffer 为 (ℝ (index ) ×
elementSize ) + offset 。
5. 令 elementType 为 TypedArrayElementType (O )。
6. 返回 GetValueFromBuffer (O .[[ViewedArrayBuffer]] , byteIndexInBuffer , elementType ,
true , unordered )。
10.4.5.16 TypedArraySetElement ( O , index ,
value )
抽象操作 TypedArraySetElement 接受参数 O (一个 TypedArray )、index (一个数字)和
value (一个 ECMAScript 语言值 ),并返回一个
包含
unused 或 抛出完成记录 。调用时执行以下步骤:
1. 如果 O .[[ContentType]] 为
bigint ,令 numValue 为 ? ToBigInt (value )。
2. 否则,令 numValue 为 ? ToNumber (value )。
3. 如果 IsValidIntegerIndex (O ,
index ) 为 true ,则:
a. 令 offset 为 O .[[ByteOffset]] 。
b. 令 elementSize 为 TypedArrayElementSize (O )。
c. 令 byteIndexInBuffer 为 (ℝ (index )
× elementSize ) + offset 。
d. 令 elementType 为 TypedArrayElementType (O )。
e. 执行 SetValueInBuffer (O .[[ViewedArrayBuffer]] , byteIndexInBuffer , elementType ,
numValue , true , unordered )。
4. 返回 unused 。
注
此操作似乎总是成功,但在尝试写入 TypedArray 的末尾或写入由已分离的 ArrayBuffer 支持的
TypedArray 时没有效果。
10.4.5.17 IsArrayBufferViewOutOfBounds ( O )
抽象操作 IsArrayBufferViewOutOfBounds 接受参数 O (一个 TypedArray 或一个 DataView),并返回一个布尔值。它检查
TypedArray 的数值属性或 DataView
对象的方法是否可以引用基础数据块边界之外的索引处的值。此抽象操作存在是为了方便上游规范。调用时执行以下步骤:
1. 如果 O 具有 [[DataView]] 内部插槽,则:
a. 令 viewRecord 为 MakeDataViewWithBufferWitnessRecord (O ,
seq-cst )。
b. 返回 IsViewOutOfBounds (viewRecord )。
2. 令 taRecord 为 MakeTypedArrayWithBufferWitnessRecord (O ,
seq-cst )。
3. 返回 IsTypedArrayOutOfBounds (taRecord )。
10.4.6 模块命名空间特殊对象
一个 模块命名空间特殊对象 是一个 特殊对象 ,它暴露了从 ECMAScript 模块 导出的绑定(参见 16.2.3 )。一个 模块命名空间特殊对象
的字符串键自身属性与模块导出的绑定名称之间存在一一对应关系。导出的绑定包括使用 export *
语法间接导出的绑定。每个字符串值自身属性键是相应导出绑定名称的 字符串值 。这些是 模块命名空间特殊对象
的唯一字符串键属性。每个这样的属性具有以下属性: { [[Writable]] : true , [[Enumerable]] : true , [[Configurable]] :
false }。模块命名空间特殊对象 是不可扩展的。
一个对象是一个 模块命名空间特殊对象 ,如果它的 [[GetPrototypeOf]] ,
[[SetPrototypeOf]] , [[IsExtensible]] , [[PreventExtensions]] , [[GetOwnProperty]] , [[DefineOwnProperty]] , [[HasProperty]] , [[Get]] , [[Set]] , [[Delete]] ,
和
[[OwnPropertyKeys]] 内部方法使用本节中的定义,而它的其他基本内部方法使用 10.1
中的定义。这些方法由 ModuleNamespaceCreate 安装。
模块命名空间特殊对象 具有 表
33 中定义的内部插槽。
表 33:模块命名空间特殊对象的内部插槽
内部插槽名称
类型
描述
[[Module]]
一个 模块记录
暴露此命名空间导出的 模块记录
[[Exports]]
一个 字符串列表
一个 列表 ,其元素是作为此对象的自身属性暴露的导出名称的字符串值。该列表的顺序就像用
%Array.prototype.sort% 使用 undefined 作为 comparefn 对这些字符串值进行排序一样。
10.4.6.1 [[GetPrototypeOf]] ( )
一个 模块命名空间特殊对象 的 [[GetPrototypeOf]] 内部方法不接收任何参数,返回一个 正常完成记录,包含
null 。它执行以下步骤:
1. 返回 null 。
10.4.6.2 [[SetPrototypeOf]] ( V )
一个 模块命名空间特殊对象 的 [[SetPrototypeOf]] 内部方法接收参数 V (一个对象或 null ),返回一个
正常完成记录,包含
一个布尔值。它执行以下步骤:
1. 返回 ! SetImmutablePrototype (O ,
V )。
10.4.6.3 [[IsExtensible]] ( )
一个 模块命名空间特殊对象 的 [[IsExtensible]] 内部方法不接收任何参数,返回一个 正常完成记录,包含
false 。它执行以下步骤:
1. 返回 false 。
10.4.6.4 [[PreventExtensions]] ( )
一个 模块命名空间特殊对象 的 [[PreventExtensions]] 内部方法不接收任何参数,返回一个 正常完成记录,包含
true 。它执行以下步骤:
1. 返回 true 。
10.4.6.5 [[GetOwnProperty]] ( P )
一个 模块命名空间特殊对象 的 [[GetOwnProperty]] 内部方法接收参数 P (一个 属性键 ),返回一个 正常完成记录,包含 一个
属性描述符 或
undefined ,或一个 抛出完成记录 。它执行以下步骤:
1. 如果 P 是一个符号 ,返回
OrdinaryGetOwnProperty (O ,
P )。
2. 让 exports 成为 O 的 [[Exports]] 。
3. 如果 exports 不包含 P ,返回
undefined 。
4. 让 value 成为 ? O .[[Get]] (P , O )。
5. 返回 PropertyDescriptor { [[Value]] :
value , [[Writable]] : true , [[Enumerable]] : true , [[Configurable]] : false }。
10.4.6.6 [[DefineOwnProperty]] ( P ,
Desc )
一个 模块命名空间特殊对象 的 [[DefineOwnProperty]] 内部方法接收参数 P (一个 属性键 )和
Desc (一个 属性描述符 ),返回一个
正常完成记录,包含
一个布尔值或一个 抛出完成记录 。它执行以下步骤:
1. 如果 P 是一个符号 ,返回
! OrdinaryDefineOwnProperty (O ,
P , Desc )。
2. 让 current 成为 ? O .[[GetOwnProperty]] (P )。
3. 如果 current 是 undefined ,返回
false 。
4. 如果 Desc 具有 [[Configurable]]
字段,并且 Desc 的 [[Configurable]] 是 true ,返回
false 。
5. 如果 Desc 具有 [[Enumerable]]
字段,并且 Desc 的 [[Enumerable]] 是 false ,返回
false 。
6. 如果 IsAccessorDescriptor (Desc )
是 true ,返回 false 。
7. 如果 Desc 具有 [[Writable]] 字段,并且
Desc 的 [[Writable]] 是 false ,返回
false 。
8. 如果 Desc 具有 [[Value]] 字段,返回
SameValue (Desc .[[Value]] , current .[[Value]] )。
9. 返回 true 。
10.4.6.7 [[HasProperty]] ( P )
一个 模块命名空间特殊对象 的 [[HasProperty]] 内部方法接收参数 P (一个 属性键 ),返回一个 正常完成记录,包含
一个布尔值。它执行以下步骤:
1. 如果 P 是一个符号 ,返回
! OrdinaryHasProperty (O ,
P )。
2. 让 exports 成为 O 的 [[Exports]] 。
3. 如果 exports 包含 P ,返回 true 。
4. 返回 false 。
10.4.6.8 [[Get]] ( P ,
Receiver )
一个 模块命名空间特殊对象 的 [[Get]] 内部方法接收参数 P (一个 属性键 )和 Receiver (一个 ECMAScript 语言值 ),返回一个
正常完成记录,包含 一个
ECMAScript 语言值 或一个
抛出完成记录 。它执行以下步骤:
1. 如果 P 是一个符号 ,则
a. 返回 ! OrdinaryGet (O ,
P , Receiver )。
2. 让 exports 成为 O 的 [[Exports]] 。
3. 如果 exports 不包含 P ,返回
undefined 。
4. 让 m 成为 O 的 [[Module]] 。
5. 让 binding 成为 m .ResolveExport(P )。
6. 断言 :binding 是一个 已解析绑定记录 。
7. 让 targetModule 成为 binding 的 [[Module]] 。
8. 断言 :targetModule 不是
undefined 。
9. 如果 binding 的 [[BindingName]]
是 namespace ,则
a. 返回 GetModuleNamespace (targetModule )。
10. 让 targetEnv 成为 targetModule 的 [[Environment]] 。
11. 如果 targetEnv 是 empty ,抛出一个
ReferenceError 异常。
12. 返回
? 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 。它执行以下步骤:
1. 返回 false 。
10.4.6.10 [[Delete]] ( P )
一个 模块命名空间特殊对象 的 [[Delete]] 内部方法接收参数 P (一个 属性键 ),返回一个 正常完成记录,包含
一个布尔值。它执行以下步骤:
1. 如果 P 是一个符号 ,则
a. 返回 ! OrdinaryDelete (O ,
P )。
2. 让 exports 成为 O 的 [[Exports]] 。
3. 如果 exports 包含 P ,返回
false 。
4. 返回 true 。
10.4.6.11 [[OwnPropertyKeys]] ( )
一个 模块命名空间特殊对象 的 [[OwnPropertyKeys]] 内部方法不接收任何参数,返回一个 正常完成记录,包含 一个
列表 的 属性键 。它执行以下步骤:
1. 让 exports 成为 O 的 [[Exports]] 。
2. 让 symbolKeys 成为 OrdinaryOwnPropertyKeys (O )。
3. 返回 列表连接 exports 和
symbolKeys 。
10.4.6.12 ModuleNamespaceCreate ( module , exports )
抽象操作 ModuleNamespaceCreate 接收参数 module (一个 模块记录 )和
exports (一个 字符串列表 ),返回一个
模块命名空间特殊对象 。它用于指定创建新的
模块命名空间特殊对象 。它执行以下步骤:
1. 断言 :module 的 [[Namespace]] 是 empty 。
2. 让 internalSlotsList 成为 表
33 中列出的内部插槽。
3. 让 M 成为 MakeBasicObject (internalSlotsList )。
4. 将 M 的基本内部方法设置为 10.4.6 中的定义。
5. 将 M 的 [[Module]] 设置为
module 。
6. 让 sortedExports 成为 列表 ,其元素是
exports 的元素,顺序就像用 %Array.prototype.sort% 使用 undefined 作为
comparefn 对这些值进行排序一样。
7. 将 M 的 [[Exports]] 设置为
sortedExports 。
8. 创建与 28.3
中定义相对应的 M 自身属性。
9. 将 module 的 [[Namespace]] 设置为
M 。
10. 返回 M 。
10.4.7 不可变原型特殊对象
一个 不可变原型特殊对象 是一个具有 [[Prototype]] 内部插槽的 特殊对象 ,该插槽在初始化后不会改变。
如果对象的 [[SetPrototypeOf]] 内部方法使用以下实现,则该对象是一个 不可变原型特殊对象 。(其其他基本内部方法可以根据具体的 不可变原型特殊对象 使用任意实现。)
注
与其他 特殊对象 不同,没有为 不可变原型特殊对象
提供专门的创建抽象操作。这是因为它们仅由 %Object.prototype%
和 宿主环境 使用,并且在 宿主环境
中,相关对象可能在其他方面也是特殊的,因此需要它们自己的专门创建操作。
10.4.7.1 [[SetPrototypeOf]] ( V )
一个 不可变原型特殊对象 的 [[SetPrototypeOf]] 内部方法接收参数 V (一个对象或 null ),并返回一个
正常完成记录,包含
一个布尔值或一个 抛出完成记录 。它执行以下步骤:
1. 返回 ? SetImmutablePrototype (O , V )。
10.4.7.2 SetImmutablePrototype ( O , V )
抽象操作 SetImmutablePrototype 接收参数 O (一个对象)和 V (一个对象或 null ),并返回一个
正常完成记录,包含
一个布尔值或一个 抛出完成记录 。它执行以下步骤:
1. 让 current 成为 ? O .[[GetPrototypeOf]] ()。
2. 如果 SameValue (V ,
current ) 是 true ,返回 true 。
3. 返回 false 。
10.5 代理对象的内部方法和内部插槽
代理对象是一个 特殊对象 ,其基本内部方法部分由 ECMAScript 代码实现。每个代理对象都有一个名为
[[ProxyHandler]] 的内部插槽。[[ProxyHandler]] 的值是一个对象,称为代理的
处理程序对象 ,或 null 。处理程序对象的方法(见 表34 )可以用来增强一个或多个代理对象的内部方法的实现。每个代理对象还有一个名为
[[ProxyTarget]] 的内部插槽,其值要么是一个对象,要么是 null 值。这个对象被称为代理的
目标对象 。
如果对象的基本内部方法(包括 [[Call]] 和 [[Construct]] ,如果适用)使用本节中的定义,则该对象是一个 代理特殊对象 。这些内部方法在 ProxyCreate 中安装。
表34: 代理处理程序方法
内部方法
处理程序方法
[[GetPrototypeOf]]
getPrototypeOf
[[SetPrototypeOf]]
setPrototypeOf
[[IsExtensible]]
isExtensible
[[PreventExtensions]]
preventExtensions
[[GetOwnProperty]]
getOwnPropertyDescriptor
[[DefineOwnProperty]]
defineProperty
[[HasProperty]]
has
[[Get]]
get
[[Set]]
set
[[Delete]]
deleteProperty
[[OwnPropertyKeys]]
ownKeys
[[Call]]
apply
[[Construct]]
construct
当调用处理程序方法来提供代理对象内部方法的实现时,处理程序方法会将代理的目标对象作为参数传递。代理的处理程序对象不一定具有与每个基本内部方法对应的方法。如果处理程序对象没有对应于内部陷阱的方法,则在代理上调用内部方法将导致调用代理目标对象上的相应内部方法。
代理对象的 [[ProxyHandler]] 和 [[ProxyTarget]]
内部插槽在对象创建时总是被初始化,并且通常不可修改。有些代理对象是以允许其随后被撤销 的方式创建的。当代理被撤销时,其 [[ProxyHandler]]
和 [[ProxyTarget]] 内部插槽被设置为 null ,导致在该代理对象上随后调用内部方法会抛出
TypeError 异常。
由于代理对象允许内部方法的实现由任意 ECMAScript 代码提供,因此可能会定义一个其处理程序方法违反 6.1.7.3
中定义的不变量的代理对象。一些在 6.1.7.3
中定义的内部方法不变量是基本的完整性不变量。这些不变量由本节中指定的代理对象内部方法明确执行。ECMAScript 实现必须在所有可能的不变量违反的情况下都具有健壮性。
在以下算法描述中,假设 O 是一个 ECMAScript 代理对象,P 是一个 属性键 值,V 是任何
ECMAScript 语言值 ,并且
Desc 是一个 属性描述符 记录。
10.5.1 [[GetPrototypeOf]] ( )
[[GetPrototypeOf]] 内部方法的
Proxy 异质对象
O 不接受任何参数,并返回
正常完成记录
,其包含一个对象或 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 。
注
Proxy 对象的 [[GetPrototypeOf]] 强制执行以下不变量:
[[GetPrototypeOf]] 的结果必须是一个对象或 null 。
如果目标对象不可扩展,则应用于代理对象的 [[GetPrototypeOf]] 必须返回与应用于代理对象的目标对象的 [[GetPrototypeOf]] 相同的值。
10.5.2 [[SetPrototypeOf]] ( V )
[[SetPrototypeOf]] 内部方法的
Proxy 异质对象
O 接受参数 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 。
注
Proxy 对象的 [[SetPrototypeOf]] 强制执行以下不变量:
[[SetPrototypeOf]] 的结果是一个布尔值。
如果目标对象不可扩展,则参数值必须与应用于目标对象的 [[GetPrototypeOf]] 的结果相同。
10.5.3 [[IsExtensible]] ( )
[[IsExtensible]] 内部方法的
Proxy 异质对象
O 不接受参数并返回一个
正常完成记录
,其包含一个布尔值或返回一个
抛出完成
。调用时执行以下步骤:
执行 ?
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 。
注
Proxy 对象的 [[IsExtensible]] 强制执行以下不变量:
[[IsExtensible]] 的结果是一个布尔值。
应用于 Proxy 对象的 [[IsExtensible]] 必须返回与应用于 Proxy 对象的目标对象相同的参数值相同的结果。
10.5.4 [[PreventExtensions]] ( )
[[PreventExtensions]] 内部方法的
Proxy 异质对象
O 不接受参数并返回一个
正常完成记录
,其包含一个布尔值或返回一个
抛出完成
。调用时执行以下步骤:
执行 ?
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 。
注
Proxy 对象的 [[PreventExtensions]] 强制执行以下不变量:
[[PreventExtensions]] 的结果是一个布尔值。
应用于 Proxy 对象的 [[PreventExtensions]] 仅当应用于 Proxy 对象的目标对象的 [[IsExtensible]] 结果为 false 时,才会返回 true 。
10.5.5 [[GetOwnProperty]] ( P )
[[GetOwnProperty]] 内部方法的
Proxy 异质对象
O 接受参数 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 。
注
Proxy 对象的 [[GetOwnProperty]] 强制执行以下不变量:
[[GetOwnProperty]] 的结果必须是一个对象或 undefined 。
如果目标对象作为自身不可配置的属性存在,则该属性不能被报告为不存在。
如果目标对象作为自身不可扩展的属性存在,则该属性不能被报告为不存在。
如果目标对象是不可扩展的,且该属性不存在于目标对象的自身属性中,则该属性不能被报告为存在。
除非目标对象的自身不可配置属性存在,否则该属性不能被报告为不可配置。
除非目标对象的自身不可配置且不可写的属性存在,否则该属性不能被报告为既不可配置又不可写。
10.5.6 [[DefineOwnProperty]] ( P ,
Desc )
[[DefineOwnProperty]] 内部方法的
Proxy 异质对象
O 接受参数 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 。
注
Proxy 对象的 [[DefineOwnProperty]] 强制执行以下不变量:
[[DefineOwnProperty]] 的结果是一个布尔值。
如果目标对象是不可扩展的,则不能添加属性。
除非目标对象存在相应的不可配置自身属性,否则属性不能是不可配置的。
除非目标对象存在相应的不可配置且不可写的自身属性,否则不可配置的属性不能是不可写的。
如果属性有相应的目标对象属性,则使用属性的属性描述符应用于目标对象的 [[DefineOwnProperty]] 不会抛出异常。
10.5.7 [[HasProperty]] ( P )
[[HasProperty]] 内部方法的
Proxy 异质对象
O 接受参数 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 。
注
Proxy 对象的 [[HasProperty]] 强制执行以下不变量:
[[HasProperty]] 的结果是一个布尔值。
如果属性作为目标对象的不可配置自身属性存在,则不能报告该属性不存在。
如果属性作为目标对象的自身属性存在且目标对象不可扩展,则不能报告该属性不存在。
10.5.8 [[Get]] ( P , Receiver )
[[Get]] 内部方法的
Proxy 异质对象
O 接受参数 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 。
注
Proxy 对象的 [[Get]] 强制执行以下不变量:
如果目标对象属性是一个不可写、不可配置的自身
数据属性
,则报告的属性值必须与相应的目标对象属性的值相同。
如果相应的目标对象属性是一个不可配置的自身
访问器属性
且其 [[Get]] 属性为 undefined ,则报告的属性值必须为
undefined 。
10.5.9 [[Set]] ( P , V ,
Receiver )
[[Set]] 内部方法的
Proxy 异质对象
O 接受参数 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 。
注
Proxy 对象的 [[Set]] 强制执行以下不变量:
[[Set]] 的结果是一个布尔值。
如果相应的目标对象属性是一个不可写、不可配置的自身
数据属性
,则不能将属性值更改为与相应的目标对象属性的值不同的值。
如果相应的目标对象属性是一个不可配置的自身
访问器属性
且其 [[Set]] 属性为 undefined ,则不能设置该属性的值。
10.5.10 [[Delete]] ( P )
[[Delete]] 内部方法的
Proxy 异质对象
O 接受参数 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 。
注
Proxy 对象的 [[Delete]] 强制执行以下不变量:
[[Delete]] 的结果是一个布尔值。
如果目标对象存在一个不可配置的自身属性,则不能将其报告为已删除。
如果目标对象存在一个自身属性且目标对象是不可扩展的,则不能将其报告为已删除。
10.5.11 [[OwnPropertyKeys]] ( )
[[OwnPropertyKeys]] 内部方法的
Proxy 异质对象
O 不接受任何参数,并返回一个
正常完成记录
,其包含一个
列表
的
属性键
或返回一个
抛出完成
。调用时执行以下步骤:
执行 ?
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 , «String, Symbol »)。
如果 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 。
注
Proxy 对象的 [[OwnPropertyKeys]] 强制执行以下不变量:
[[OwnPropertyKeys]] 的结果是一个
列表
。
返回的
列表
不包含重复项。
每个结果
列表
元素的类型是字符串或符号。
结果
列表
必须包含目标对象所有不可配置自身属性的键。
如果目标对象是不可扩展的,则结果
列表
必须包含目标对象自身属性的所有键且不包含其他值。
10.5.12 [[Call]] ( thisArgument ,
argumentsList )
[[Call]] 内部方法用于 Proxy 异域对象 O 。它接受参数
thisArgument (一个 ECMAScript 语言值 )和
argumentsList (一个 列表 ,包含 ECMAScript 语言值 ),并返回一个包含
正常完成记录 ,其中包含一个
ECMAScript 语言值 或者一个
抛出完成记录 。它在被调用时执行以下步骤:
1. 执行 ? ValidateNonRevokedProxy (O ).
2. 让 target 等于 O .[[ProxyTarget]] .
3. 让 handler 等于 O .[[ProxyHandler]] .
4. 断言 : handler 是一个对象。
5. 让 trap 等于 ? GetMethod (handler ,
"apply").
6. 如果 trap 是 undefined,则
a. 返回 ? Call (target ,
thisArgument , argumentsList ).
7. 让 argArray 等于 CreateArrayFromList (argumentsList ).
8. 返回 ? Call (trap , handler , «
target , thisArgument , argArray »).
注
Proxy 异域对象 只有在其 [[ProxyTarget]] 内部槽的初始值是一个具有 [[Call]] 内部方法的对象时,才具有 [[Call]] 内部方法。
10.5.13 [[Construct]] ( argumentsList ,
newTarget )
[[Construct]] 内部方法用于 Proxy 异域对象 O 。它接受参数
argumentsList (一个 列表 ,包含 ECMAScript 语言值 )和
newTarget (一个 构造函数 ),并返回一个包含对象的 正常完成记录 或一个
抛出完成记录 。它在被调用时执行以下步骤:
1. 执行 ? ValidateNonRevokedProxy (O ).
2. 让 target 等于 O .[[ProxyTarget]] .
3. 断言 : IsConstructor (target ) 为
true。
4. 让 handler 等于 O .[[ProxyHandler]] .
5. 断言 : handler 是一个对象。
6. 让 trap 等于 ? GetMethod (handler ,
"construct").
7. 如果 trap 是 undefined,则
a. 返回 ? Construct (target ,
argumentsList , newTarget ).
8. 让 argArray 等于 CreateArrayFromList (argumentsList ).
9. 让 newObj 等于 ? Call (trap , handler , «
target , argArray , newTarget »).
10. 如果 newObj 不是一个对象,抛出一个 TypeError 异常。
11. 返回 newObj .
注 1
Proxy 异域对象 只有在其 [[ProxyTarget]] 内部槽的初始值是一个具有 [[Construct]] 内部方法的对象时,才具有
[[Construct]] 内部方法。
注 2
[[Construct]] 对于 Proxy 对象强制执行以下不变量:
[[Construct]] 的结果必须是一个对象。
10.5.14 ValidateNonRevokedProxy ( proxy )
抽象操作 ValidateNonRevokedProxy 接受参数 proxy (一个 Proxy 异域对象 ),并返回包含
正常完成记录 的
unused 或者一个 抛出完成记录 。如果
proxy 已被撤销,则抛出 TypeError 异常。它在被调用时执行以下步骤:
1. 如果 proxy .[[ProxyTarget]] 是
null ,抛出 TypeError 异常。
2. 断言 : proxy .[[ProxyHandler]] 不是 null 。
3. 返回 unused 。
10.5.15 ProxyCreate ( target , handler )
抽象操作 ProxyCreate 接受参数 target (一个 ECMAScript
语言值 )和 handler (一个 ECMAScript
语言值 ),并返回包含 正常完成记录 的
Proxy 异域对象 或一个 抛出完成记录 。它用于指定新
Proxy 对象的创建。它在被调用时执行以下步骤:
1. 如果 target 不是一个对象 ,抛出
TypeError 异常。
2. 如果 handler 不是一个对象 ,抛出
TypeError 异常。
3. 让 P 等于 MakeBasicObject (« [[ProxyHandler]] , [[ProxyTarget]] »)。
4. 设置 P 的基本内部方法,除了 [[Call]] 和 [[Construct]] ,按照 10.5
中的定义。
5. 如果 IsCallable (target ) 为
true ,则
a. 设置 P .[[Call]] ,如 10.5.12
中所述。
b. 如果 IsConstructor (target )
为 true ,则
i. 设置 P .[[Construct]] ,如
10.5.13
中所述。
6. 设置 P .[[ProxyTarget]] 为
target 。
7. 设置 P .[[ProxyHandler]] 为
handler 。
8. 返回 P 。
11 ECMAScript 语言:源代码
11.1 源代码
语法
SourceCharacter
::
任何 Unicode 代码点
ECMAScript 源代码 是一系列 Unicode 代码点。在 ECMAScript 语法允许的地方,所有从 U+0000 到 U+10FFFF 的 Unicode
代码点值,包括代理代码点,都可以出现在 ECMAScript 源代码中。用于存储和交换 ECMAScript 源代码的实际编码与本规范无关。不论外部源代码编码如何,符合规范的 ECMAScript
实现都将源代码处理为等效的 SourceCharacter 值序列,每个 SourceCharacter 都是一个
Unicode 代码点。符合规范的 ECMAScript 实现不要求对源代码进行任何规范化,或表现得像在执行源代码的规范化。
组合字符序列的组成部分被视为单独的 Unicode 代码点,即使用户可能将整个序列视为一个字符。
注
在字符串字面量、正则表达式字面量、模板字面量和标识符中,任何 Unicode 代码点也可以使用 Unicode 转义序列来表示,显式表达代码点的数值。在注释中,这样的转义序列实际上被忽略,作为注释的一部分。
ECMAScript 与 Java 编程语言在 Unicode 转义序列的行为上有所不同。例如,在 Java 程序中,如果 Unicode 转义序列 \u000A
出现在单行注释中,它会被解释为行终止符(Unicode 代码点 U+000A 是换行符(LF)),因此下一个代码点不再是注释的一部分。同样,如果 Unicode 转义序列 \u000A
出现在 Java 程序的字符串字面量中,它也会被解释为行终止符,字符串字面量中不允许有行终止符——必须写成 \n
而不是
\u000A
,以使换行符(LF)成为字符串字面量的字符串值的一部分。在 ECMAScript 程序中,出现在注释中的 Unicode 转义序列从不被解释,因此不能终止注释。同样,出现在
ECMAScript 程序的字符串字面量中的 Unicode 转义序列始终是字面量的一部分,永远不会被解释为行终止符或可能终止字符串字面量的代码点。
11.1.1 静态语义: UTF16EncodeCodePoint ( cp )
抽象操作 UTF16EncodeCodePoint 接受参数 cp (一个 Unicode 代码点)并返回一个字符串。调用时,它执行以下步骤:
1. 断言 : 0 ≤ cp ≤ 0x10FFFF。
2. 如果 cp ≤ 0xFFFF,返回由数值为 cp 的代码单元组成的字符串值。
3. 令 cu1 为数值为 向下取整 ((cp - 0x10000) / 0x400) +
0xD800 的代码单元。
4. 令 cu2 为数值为 ((cp - 0x10000) 模 0x400) +
0xDC00 的代码单元。
5. 返回 字符串连接 cu1 和
cu2 的结果。
11.1.2 静态语义: CodePointsToString ( text )
抽象操作 CodePointsToString 接受参数 text (一个 Unicode 代码点序列)并返回一个字符串。它将 text 转换为字符串值,如
6.1.4
中所述。调用时,它执行以下步骤:
1. 令 result 为空字符串。
2. 对于 text 中的每个代码点 cp ,执行以下步骤
a. 将 result 设为 字符串连接
result 和 UTF16EncodeCodePoint (cp )
的结果。
3. 返回 result 。
11.1.3 静态语义: UTF16SurrogatePairToCodePoint ( lead , trail
)
抽象操作 UTF16SurrogatePairToCodePoint 接受参数 lead (一个代码单元)和 trail (一个代码单元),并返回一个代码点。形成
UTF-16 代理对 的两个代码单元将转换为一个代码点。调用时,它执行以下步骤:
1. 断言 : lead 是一个 前导代理项 并且 trail 是一个
尾随代理项 。
2. 令 cp 为 (lead - 0xD800) × 0x400 +
(trail - 0xDC00) + 0x10000。
3. 返回代码点 cp 。
11.1.4 静态语义: CodePointAt ( string , position )
抽象操作 CodePointAt 接受参数 string (一个字符串)和 position (一个非负 整数 ),并返回一个包含字段 [[CodePoint]] (一个代码点)、[[CodeUnitCount]] (一个正的 整数 )、[[IsUnpairedSurrogate]] (一个布尔值)的 记录 。它将
string 解释为 UTF-16 编码的代码点序列,如 6.1.4 中所述,并从索引
position 处的代码单元开始读取单个代码点。调用时,它执行以下步骤:
1. 令 size 为 string 的长度。
2. 断言 : position ≥ 0 并且
position
< size 。
3. 令 first 为 string 内索引 position
处的代码单元。
4. 令 cp 为数值为 first 的代码点。
5. 如果 first 既不是 前导代理项 也不是
尾随代理项 ,则
a. 返回 记录 { [[CodePoint]] : cp , [[CodeUnitCount]] : 1,
[[IsUnpairedSurrogate]] : false }。
6. 如果 first 是 尾随代理项 或者
position + 1 = size ,则
a. 返回 记录 { [[CodePoint]] : cp , [[CodeUnitCount]] : 1,
[[IsUnpairedSurrogate]] : true }。
7. 令 second 为 string 内索引 position + 1
处的代码单元。
8. 如果 second 不是 尾随代理项 ,则
a. 返回 记录 { [[CodePoint]] : cp , [[CodeUnitCount]] : 1,
[[IsUnpairedSurrogate]] : true }。
9. 将 cp 设置为 UTF16SurrogatePairToCodePoint (first ,
second )。
10. 返回 记录 { [[CodePoint]] : cp , [[CodeUnitCount]] : 2, [[IsUnpairedSurrogate]] : false }。
11.1.5 静态语义: StringToCodePoints ( string )
抽象操作 StringToCodePoints 接受参数 string (一个字符串)并返回一个代码点的 列表 。它返回将
string 解释为 UTF-16 编码的 Unicode 文本后得到的 Unicode 代码点序列,如 6.1.4
中所述。调用时,它执行以下步骤:
1. 令 codePoints 为一个新的空的 列表 。
2. 令 size 为 string 的长度。
3. 令 position 为 0。
4. 重复,当 position 小于 size 时,
a. 令 cp 为 CodePointAt (string ,
position )。
b. 将 cp .[[CodePoint]] 添加到
codePoints 。
c. 将 position 设置为 position +
cp .[[CodeUnitCount]] 。
5. 返回 codePoints 。
11.1.6 静态语义: ParseText ( sourceText , goalSymbol )
抽象操作 ParseText 接受参数 sourceText (一个 Unicode 代码点序列)和 goalSymbol (ECMAScript
语法中的一个非终结符)并返回一个 解析节点 或一个非空的 列表 ,其中包含
SyntaxError 对象。调用时,它执行以下步骤:
1. 尝试使用 goalSymbol 作为目标符号 解析
sourceText ,并分析解析结果是否有 早期错误 条件。解析和 早期错误 检测可以以 实现定义 的方式交错进行。
2. 如果解析成功且没有发现早期错误 ,则返回解析节点 (goalSymbol
的一个实例),该节点位于解析树的根节点。
3. 否则,返回一个包含一个或多个 SyntaxError 对象的列表 ,这些对象表示解析错误和/或
早期错误 。如果存在多个解析错误或 早期错误 ,则列表中的错误对象数量和排序是实现定义 的,但至少必须存在一个。
注 1
考虑一个在特定点有早期错误 的文本,并且在后续点有语法错误。一个先进行解析然后进行早期错误 检测的实现可能会报告语法错误并且不进行早期错误 检测。一个将两者交错进行的实现可能会报告早期错误 并且不继续发现语法错误。第三个实现可能会报告两个错误。这些行为都是符合规范的。
注 2
11.2 Types of Source Code
有四种类型的 ECMAScript 代码:
Note 1
Function code 通常以函数定义的主体形式提供(15.2 ),箭头函数定义(15.3 ),方法定义(15.4 ),生成器函数定义(15.5 ),异步函数定义(15.8 ),异步生成器函数定义(15.6 ),和异步箭头函数(15.9 )。Function
code 也来源于 Function 构造函数(constructor )(20.2.1.1 ),GeneratorFunction
构造函数(constructor )(27.3.1.1 ),以及 AsyncFunction
构造函数(constructor )(27.7.1.1 )的参数。
Note 2
将 BindingIdentifier
包含在函数代码中的实际效果是,即使周围代码不是 严格模式代码 ,包含 "use strict" 指令的函数体名称为
BindingIdentifier 的函数仍然会应用
严格模式代码 的早期错误。
11.2.1 指令序言和 "use strict" 指令
指令序言 是出现在
StatementListItem
或 ModuleItem
的初始位置处的最长序列
ExpressionStatement 。这些
ExpressionStatement
以一个 StringLiteral
标记及后续的分号组成。这个分号可以是显式的,也可以由自动分号插入
(12.10 )。
指令序言
可以是一个空序列。
"use strict" 指令 是出现在
指令序言
中的 ExpressionStatement ,其
StringLiteral
为精确的代码点序列 "use strict"
或 'use strict'
。
"use strict" 指令
不应包含 EscapeSequence
或 LineContinuation 。
指令序言
可以包含多个 "use strict" 指令 。
但是,如果出现这种情况,实施可能会发出警告。
注
11.2.2 严格模式代码
ECMAScript 语法单元可以使用无限制或严格模式语法和语义进行处理
(4.3.2 )。在以下情况下,代码被解释为
严格模式代码 :
不是严格模式代码的 ECMAScript 代码称为 非严格代码 。
11.2.3 非 ECMAScript 函数
ECMAScript 实现可能支持对函数 异质对象
的求值,其求值行为以某种 宿主定义
的可执行代码形式表达,而不是 ECMAScript 源文本 。无论
函数对象
是在 ECMAScript 代码中定义的,还是内置函数,从调用或被调用的 ECMAScript 代码的角度来看,都是不可观察的。
12 ECMAScript 语言:词法语法
ECMAScript 脚本 或模块 的源文本首先被转换为一系列输入元素,这些输入元素包括标记、行终止符、注释或空白。源文本从左到右扫描,反复采用最长可能的代码点序列作为下一个输入元素。
在多个情况下,词法输入元素的识别对消耗输入元素的语法语境是敏感的。这需要词法语法的多个目标符号 。InputElementHashbangOrRegExp 目标在脚本 或模块 的开头使用。InputElementRegExpOrTemplateTail 目标在语法语境中使用,其中允许正则表达式文本 、模板中间 或模板尾部 。InputElementRegExp 目标符号 在所有允许正则表达式文本 但不允许模板中间 或模板尾部 的语法语境中使用。InputElementTemplateTail 目标在所有允许模板中间 或模板尾部 但不允许正则表达式文本 的语法语境中使用。在所有其他语境中,InputElementDiv 用作词法目标符号 。
Note
使用多个词法目标确保没有词法歧义会影响自动分号插入。例如,没有语法语境同时允许前导除法或除法赋值和前导正则表达式文本 。这不受分号插入的影响(见12.10 );例如以下情况:
a = b
/hi/g.exec (c).map (d);
在一个行终止符 之后的第一个非空白、非注释代码点是U+002F(SOLIDUS),且语法上下文允许除法或除法赋值,不会在行终止符 处插入分号。也就是说,上述示例的解释方式与以下相同:
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+200C(零宽非连接符)和 U+200D(零宽连接符)是用于在某些语言中形成单词或短语时进行必要区分的格式控制字符。在 ECMAScript 源文本
中,这些代码点也可以在第一个字符之后用于 IdentifierName 中。
U+FEFF(零宽不换行空格)是主要用于文本开头的格式控制字符,用来标记它为 Unicode 并允许检测文本的编码和字节顺序。出于这种目的而使用的 <ZWNBSP>
字符有时也会出现在文本的开头之后,例如由于文件连接的结果。在 ECMAScript 源文本 中,<ZWNBSP>
代码点被视为空白字符(见 12.2 )。
某些格式控制字符在注释、字符串字面量和正则表达式字面量之外的特殊处理在 表 35 中总结。
表 35: 格式控制代码点的使用
12.2 空白符
空白符代码点用于提高源文本的可读性,并将词法单元(不可分割的词法单位)彼此分开,但除此之外没有其他意义。空白符代码点可以出现在任意两个词法单元之间,以及输入的开头或结尾。空白符代码点可以出现在 StringLiteral 、RegularExpressionLiteral 、Template 或 TemplateSubstitutionTail
中,在这些情况下,它们被视为构成字面值一部分的有效代码点。它们也可以出现在 Comment 中,但不能出现在任何其他类型的词法单元中。
ECMAScript 的空白符代码点列在 表 36 中。
表 36: 空白符代码点
代码点
名称
缩写
U+0009
CHARACTER TABULATION
<TAB>
U+000B
LINE TABULATION
<VT>
U+000C
FORM FEED (FF)
<FF>
U+FEFF
ZERO WIDTH NO-BREAK SPACE
<ZWNBSP>
general category 中的任意代码点 “Space_Separator”
<USP>
注 1
U+0020 (SPACE) 和 U+00A0 (NO-BREAK SPACE) 代码点是 <USP> 的一部分。
注 2
除了表 表 36 中列出的代码点外,ECMAScript
的 WhiteSpace
有意排除了所有具有 Unicode “White_Space” 属性但未分类为 general category “Space_Separator” (“Zs”) 的代码点。
语法
WhiteSpace
::
<TAB>
<VT>
<FF>
<ZWNBSP>
<USP>
12.3 行终止符
像空白符代码点一样,行终止符代码点用于提高源文本的可读性,并将词法单元(不可分割的词法单位)彼此分开。然而,与空白符代码点不同,行终止符对语法规则的行为有一定影响。通常,行终止符可以出现在任意两个词法单元之间,但在某些地方,语法规则禁止它们的出现。行终止符还会影响自动分号插入的过程(12.10 )。行终止符不能出现在任何词法单元内部,除了
StringLiteral 、Template 或 TemplateSubstitutionTail 。<LF>
和 <CR> 行终止符不能出现在 StringLiteral 词法单元中,除非作为 LineContinuation
的一部分。
行终止符可以出现在 MultiLineComment 中,但不能出现在 SingleLineComment 中。
行终止符包含在正则表达式中的 \s
类匹配的空白符代码点集合中。
ECMAScript 行终止符代码点列在 表 37 中。
表 37: 行终止符代码点
代码点
Unicode 名称
缩写
U+000A
LINE FEED (LF)
<LF>
U+000D
CARRIAGE RETURN (CR)
<CR>
U+2028
LINE SEPARATOR
<LS>
U+2029
PARAGRAPH SEPARATOR
<PS>
只有表 表 37 中的 Unicode
代码点被视为行终止符。其他新的行或换行 Unicode 代码点不被视为行终止符,但如果它们符合 表 36
中列出的要求,则被视为空白符。序列 <CR><LF> 通常用作行终止符。出于报告行号的目的,应将其视为单个 SourceCharacter 。
语法
LineTerminator
::
<LF>
<CR>
<LS>
<PS>
LineTerminatorSequence
::
<LF>
<CR>
[lookahead ≠ <LF> ]
<LS>
<PS>
<CR>
<LF>
12.5 Hashbang 注释
Hashbang 注释是位置敏感的,并且像其他类型的注释一样,从语法解析的输入元素流中被丢弃。
语法
12.6 词法单元(Tokens)
语法
CommonToken
::
IdentifierName
PrivateIdentifier
Punctuator
NumericLiteral
StringLiteral
Template
Note
12.7 名称和关键字
IdentifierName
和
ReservedWord
是根据 Unicode Standard Annex #31, Identifier and Pattern Syntax 所给出的默认标识符语法解释的词法单元,并进行了一些小的修改。
ReservedWord
是
IdentifierName
的一个枚举子集。语法定义了
Identifier
为不属于
ReservedWord
的
IdentifierName
。Unicode 标识符语法基于 Unicode 标准所定义的字符属性。所有符合 ECMAScript 实现的标识符都必须按照最新版本的 Unicode 标准中的指定类别处理 Unicode 代码点。ECMAScript
实现可以识别在 Unicode 标准的后续版本中定义的标识符代码点。
注 1
本标准指定了特定的代码点添加:U+0024 (美元符号) 和 U+005F (下划线) 在
IdentifierName
的任何地方都允许使用,并且 U+200C (零宽度非连接符) 和 U+200D (零宽度连接符) 在
IdentifierName
的第一个代码点之后的任何地方都允许使用。
语法
PrivateIdentifier
::
#
IdentifierName
IdentifierName
::
IdentifierStart
IdentifierName
IdentifierPart
IdentifierStart
::
IdentifierStartChar
\
UnicodeEscapeSequence
IdentifierPart
::
IdentifierPartChar
\
UnicodeEscapeSequence
IdentifierStartChar
::
UnicodeIDStart
$
_
IdentifierPartChar
::
UnicodeIDContinue
$
<ZWNJ>
<ZWJ>
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 标识符名称
在 IdentifierName
中允许使用 Unicode 转义序列,其中它们贡献了一个等于
IdentifierCodePoint
的单个 Unicode 代码点
UnicodeEscapeSequence
。在转义序列前的 \
不贡献任何代码点。Unicode 转义序列不能用于对
IdentifierName
贡献一个代码点,该代码点本来就是无效的。换句话说,如果将 \ Unicode 转义序列替换为它所贡献的
SourceCharacter
,结果仍然必须是一个有效的
IdentifierName
,并且与原始的
IdentifierName
拥有完全相同的
SourceCharacter
序列。在本规范中的所有标识符名称解释都是基于它们的实际代码点的,无论是否使用转义序列对任何特定的代码点进行贡献。
根据 Unicode 标准,两个规范等效的
IdentifierName
是不相等的,除非在替换每个 Unicode 转义序列后,它们由完全相同的代码点序列表示。
12.7.1.1 静态语义:早期错误
IdentifierStart
::
\
UnicodeEscapeSequence
IdentifierPart
::
\
UnicodeEscapeSequence
12.7.1.2 静态语义:IdentifierCodePoints
语法导向操作
IdentifierCodePoints
不接受任何参数,并返回一个代码点列表。它在以下各生成式上分段定义:
IdentifierName
::
IdentifierStart
让 cp 为 IdentifierCodePoint 的
IdentifierStart 。
返回 « cp »。
IdentifierName
::
IdentifierName
IdentifierPart
让 cps 为 IdentifierCodePoints 派生出的
IdentifierName 。
让 cp 为 IdentifierCodePoint 的
IdentifierPart 。
返回 列表串联 的 cps 和 «
cp »。
12.7.1.3 静态语义:IdentifierCodePoint
语法导向操作
IdentifierCodePoint
不接受任何参数并返回一个代码点。它在以下各生成式上分段定义:
IdentifierStart
::
IdentifierStartChar
返回 IdentifierStartChar 匹配的代码点。
IdentifierPart
::
IdentifierPartChar
返回 IdentifierPartChar 匹配的代码点。
UnicodeEscapeSequence
::
u
Hex4Digits
返回数值为 Hex4Digits 的代码点。
UnicodeEscapeSequence
::
u{
CodePoint
}
返回数值为 CodePoint 的代码点。
12.7.2 关键字和保留字
关键字 是一个与
IdentifierName
匹配的词法单元,但它还有一个语法用途;也就是说,它以某种语法形式出现在某些语法生成式中,例如
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
::
之一
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
元素的字面序列。关键字中的代码点不能通过 \
Unicode 转义序列表示。
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
::
之一
{ ( ) [ ] .
... ; , < >
<=
>= == != === !==
+
- * % ** ++ --
<< >> >>> &
|
^ ! ~ && ||
??
? : = += -= *=
%= **= <<= >>=
>>>=
&= |= ^= &&= ||=
??= =>
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
紧跟在 SourceCharacter 后面的 NumericLiteral 不能是
IdentifierStart 或 DecimalDigit 。
注
例如:3in
是错误的,而不是两个输入元素 3
和 in
。
12.9.3.1 静态语义:早期错误
NumericLiteral
:: LegacyOctalIntegerLiteral
DecimalIntegerLiteral
:: NonOctalDecimalIntegerLiteral
注
12.9.3.2 静态语义:MV
数值字面量表示 Number 类型 或
BigInt 类型
的值。
12.9.3.3 静态语义:NumericValue
语法定向操作
NumericValue 不接受参数,并返回一个 Number 或 BigInt。它在以下产生式上逐段定义:
NumericLiteral
::
DecimalLiteral
1. 返回 RoundMVResult (DecimalLiteral
的 MV)。
NumericLiteral
::
NonDecimalIntegerLiteral
1. 返回 𝔽 (NonDecimalIntegerLiteral
的 MV)。
NumericLiteral
::
LegacyOctalIntegerLiteral
1. 返回 𝔽 (LegacyOctalIntegerLiteral
的 MV)。
NumericLiteral
::
NonDecimalIntegerLiteral
BigIntLiteralSuffix
1. 返回 BigInt 值 的 MV
NonDecimalIntegerLiteral 。
DecimalBigIntegerLiteral
::
0
BigIntLiteralSuffix
1. 返回 0 ℤ 。
DecimalBigIntegerLiteral
::
NonZeroDigit
BigIntLiteralSuffix
1. 返回 BigInt 值 的 MV
NonZeroDigit 。
DecimalBigIntegerLiteral
::
NonZeroDigit
DecimalDigits
BigIntLiteralSuffix
NonZeroDigit
NumericLiteralSeparator
DecimalDigits
BigIntLiteralSuffix
1. 让 n 为 DecimalDigits 中代码点的数量,排除所有
NumericLiteralSeparator
的出现。
2. 让 mv 为 (NonZeroDigit 的 MV × 10** n ) 加上
DecimalDigits 的 MV。
3. 返回 ℤ (mv )。
12.9.4 字符串字面量
注 1
字符串字面量是用单引号或双引号括起来的 0 个或更多 Unicode 代码点。Unicode 代码点也可以通过转义序列表示。除了闭合引号的代码点、U+005C(反斜杠)、U+000D(回车符)和
U+000A(换行符)外,所有代码点都可以直接出现在字符串字面量中。任何代码点都可以以转义序列的形式出现。字符串字面量求值为 ECMAScript 字符串值。在生成这些字符串值时,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
的一部分以产生空代码点序列。在字符串字面量的字符串值中包含它们的正确方法是使用转义序列,如 \n
或 \u000A
。
12.9.4.1 静态语义:早期错误
EscapeSequence
::
LegacyOctalEscapeSequence
NonOctalDecimalEscapeSequence
注 1
注 2
字符串字面量可能会出现在将包围代码置于 严格模式 中的 使用严格指令
之前,实施时必须注意对这些字面量执行上述规则。例如,以下源文本包含一个语法错误:
function invalid ( ) { "\7" ; "use strict" ; }
12.9.4.2 静态语义:SV
语法定向操作
SV 不接受参数,并返回一个字符串。
字符串字面量表示 字符串类型 的值。SV
通过递归应用字符串字面量的各个部分来生成字符串值。在这个过程中,字符串字面量中的一些 Unicode 代码点被解释为具有 数学值 ,如下所述或在
12.9.3 中描述。
表 38: 字符串单字符转义序列
转义序列
代码单元值
Unicode 字符名称
符号
\b
0x0008
退格符
<BS>
\t
0x0009
字符制表符
<HT>
\n
0x000A
换行符 (LF)
<LF>
\v
0x000B
行制表符
<VT>
\f
0x000C
换页符 (FF)
<FF>
\r
0x000D
回车符 (CR)
<CR>
\"
0x0022
引号
"
\'
0x0027
撇号
'
\\
0x005C
反斜杠
\
12.9.4.3 静态语义:MV
12.9.5 正则表达式字面量
注 1
正则表达式字面量是一个输入元素,每次评估该字面量时都会转换为一个 RegExp 对象(参见 22.2 )。程序中的两个正则表达式字面量评估为永远不会相互比较为
===
的正则表达式对象,即使这两个字面量的内容相同。也可以通过 new RegExp
或调用 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
但不包括 * 、\ 、/ 或 [
RegularExpressionBackslashSequence
RegularExpressionClass
RegularExpressionChar
::
RegularExpressionNonTerminator
但不包括 \ 、/ 或 [
RegularExpressionBackslashSequence
RegularExpressionClass
RegularExpressionBackslashSequence
::
\
RegularExpressionNonTerminator
RegularExpressionNonTerminator
::
SourceCharacter
但不包括 LineTerminator
RegularExpressionClass
::
[
RegularExpressionClassChars
]
RegularExpressionClassChars
::
[empty]
RegularExpressionClassChars
RegularExpressionClassChar
RegularExpressionClassChar
::
RegularExpressionNonTerminator
但不包括 ] 或 \
RegularExpressionBackslashSequence
RegularExpressionFlags
::
[empty]
RegularExpressionFlags
IdentifierPartChar
注 2
正则表达式字面量不能为空;而不是表示一个空的正则表达式字面量,代码单元序列 //
启动一个单行注释。要指定一个空的正则表达式,请使用:/(?:)/
。
12.9.5.1 静态语义:BodyText
语法导向操作
BodyText 不接受任何参数并返回源文本。它分段定义于以下生成式:
RegularExpressionLiteral
::
/
RegularExpressionBody
/
RegularExpressionFlags
1. 返回被识别为 RegularExpressionBody
的源文本。
12.9.5.2 静态语义:FlagText
语法导向操作
FlagText 不接受任何参数并返回源文本。它分段定义于以下生成式:
RegularExpressionLiteral
::
/
RegularExpressionBody
/
RegularExpressionFlags
1. 返回被识别为 RegularExpressionFlags
的源文本。
12.9.6 模板字面量词法组件
语法
Template
::
NoSubstitutionTemplate
TemplateHead
NoSubstitutionTemplate
::
`
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
但不包括 ` 、\ 、$ 或 LineTerminator
TemplateEscapeSequence
::
CharacterEscapeSequence
0
[lookahead ∉ DecimalDigit ]
HexEscapeSequence
UnicodeEscapeSequence
NotEscapeSequence
::
0
DecimalDigit
DecimalDigit
但不包括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]
但只有当 HexDigits 的 MV > 0x10FFFF
时
CodePoint
::
HexDigits [~Sep]
但只有当 HexDigits 的 MV ≤ 0x10FFFF
时
注
12.9.6.1 静态语义:TV
语法导向操作
TV 不接受参数并返回字符串或undefined 。模板字面量组件由 TV 解释为 字符串类型 的值。TV
用于构造模板对象的索引组件(俗称模板值)。在 TV 中,转义序列由转义序列表示的 Unicode 代码点的 UTF-16 代码单元替换。
12.9.6.2 静态语义:TRV
语法导向操作
TRV 不接受参数并返回字符串。模板字面量组件由 TRV 解释为字符串类型 的值。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 条款所述。
分号插入有三条基本规则:
当从左到右解析源文本时,遇到不允许的令牌(称为冒犯令牌 )时,如果以下条件之一为真,
则会在冒犯令牌之前自动插入分号:
冒犯令牌与前一个令牌之间至少有一个
行终止符 分隔。
冒犯令牌是}
。
前一个令牌是)
,插入的分号将被解析为do-while语句的终止分号
(
14.7.2 )。
当从左到右解析源文本时,遇到输入令牌流的结尾并且解析器无法将输入令牌流解析为目标非终结符的单个实例时,
则在输入流的结尾自动插入分号。
当从左到右解析源文本时,遇到某些语法规则允许的令牌,但该语法规则是受限规则 ,并且该令牌是紧跟在标注
“[no
行终止符 here]”之后的受限规则中的第一个令牌
(因此称为受限令牌),并且受限令牌与前一个令牌之间至少有一个
行终止符 分隔时,
则在受限令牌之前自动插入分号。
但是,前述规则有一个额外的优先条件:如果分号将被解析为空语句或成为for
语句头中的两个分号之一,
则不会自动插入分号(见
14.7.4 )。
注
以下是语法中唯一的受限规则:
UpdateExpression
[Yield, Await] :
LeftHandSideExpression
[?Yield, ?Await]
[no
行终止符 here]
++
LeftHandSideExpression
[?Yield, ?Await]
[no
行终止符 here]
--
ContinueStatement
[Yield, Await] :
continue
;
continue
[no
行终止符 here]
LabelIdentifier
[?Yield, ?Await]
;
BreakStatement
[Yield, Await] :
break
;
break
[no
行终止符 here]
LabelIdentifier
[?Yield, ?Await]
;
ReturnStatement
[Yield, Await] :
return
;
return
[no
行终止符 here]
Expression
[+In, ?Yield, ?Await]
;
ThrowStatement
[Yield, Await] :
throw
[no
行终止符 here]
Expression
[+In, ?Yield, ?Await]
;
YieldExpression
[In, Await] :
yield
yield
[no
行终止符 here]
AssignmentExpression
[?In, +Yield, ?Await]
yield
[no
行终止符 here]
*
AssignmentExpression
[?In, +Yield, ?Await]
ArrowFunction
[In, Yield, Await] :
ArrowParameters
[?Yield, ?Await]
[no
行终止符 here]
=>
ConciseBody
[?In]
AsyncFunctionDeclaration
[Yield, Await, Default] :
async
[no
行终止符 here]
function
BindingIdentifier
[?Yield, ?Await]
(
FormalParameters
[~Yield, +Await]
)
{
AsyncFunctionBody
}
[+Default]
async
[no
行终止符 here]
function
(
FormalParameters
[~Yield, +Await]
)
{
AsyncFunctionBody
}
AsyncFunctionExpression
:
async
[no
行终止符 here]
function
BindingIdentifier
[~Yield, +Await] opt
(
FormalParameters
[~Yield, +Await]
)
{
AsyncFunctionBody
}
AsyncMethod
[Yield, Await] :
async
[no
行终止符 here]
ClassElementName
[?Yield, ?Await]
(
UniqueFormalParameters
[~Yield, +Await]
)
{
AsyncFunctionBody
}
AsyncGeneratorDeclaration
[Yield, Await, Default] :
async
[no
行终止符 here]
function
*
BindingIdentifier
[?Yield, ?Await]
(
FormalParameters
[+Yield, +Await]
)
{
AsyncGeneratorBody
}
[+Default]
async
[no
行终止符 here]
function
*
(
FormalParameters
[+Yield, +Await]
)
{
AsyncGeneratorBody
}
AsyncGeneratorExpression
:
async
[no
行终止符 here]
function
*
BindingIdentifier
[+Yield, +Await] opt
(
FormalParameters
[+Yield, +Await]
)
{
AsyncGeneratorBody
}
AsyncGeneratorMethod
[Yield, Await] :
async
[no
行终止符 here]
*
ClassElementName
[?Yield, ?Await]
(
UniqueFormalParameters
[+Yield, +Await]
)
{
AsyncGeneratorBody
}
AsyncArrowFunction
[In, Yield, Await] :
async
[no
行终止符 here]
AsyncArrowBindingIdentifier
[?Yield]
[no
行终止符 here]
=>
AsyncConciseBody
[?In]
CoverCallExpressionAndAsyncArrowHead
[?Yield, ?Await]
[no
行终止符 here]
=>
AsyncConciseBody
[?In]
AsyncArrowHead
:
async
[no
行终止符 here]
ArrowFormalParameters
[~Yield, +Await]
这些受限规则的实际效果如下:
当遇到++
或--
令牌且解析器将其视为后缀操作符,并且前一个令牌与++
或--
令牌之间至少有一个
行终止符 时,
则在++
或--
令牌之前自动插入分号。
当遇到continue
、break
、return
、throw
或
yield
令牌并且在下一个令牌之前遇到一个
行终止符 时,
则在continue
、break
、return
、throw
或
yield
令牌之后自动插入分号。
当箭头函数的参数之后有一个
行终止符 且在=>
令牌之前时,自动插入分号并且标点符号会导致语法错误。
当async
令牌之后有一个
行终止符 且在
function
或
标识符名称 或
(
令牌之前时,自动插入分号并且async
令牌不会被视为与后续令牌相同的表达式或类元素。
当async
令牌之后有一个
行终止符 且在
*
令牌之前时,自动插入分号并且标点符号会导致语法错误。
因此,对ECMAScript程序员的实际建议是:
后缀++
或--
操作符应与其操作数在同一行。
在return
或throw
语句中的
表达式 或在
yield
表达式中的
赋值表达式 应从
return
、throw
或yield
令牌所在的同一行开始。
在break
或continue
语句中的
标签标识符 应与
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
语句要返回的值,因为 return
与 a + b
之间有一个 行终止符
分隔。
以下源代码
a = b
++c
通过自动分号插入会被转换为以下内容:
a = b;
++c;
注 2
符号 ++
不会被视为应用于变量 b
的后缀运算符,因为 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 自动分号插入和“[无 行终止符 这里]”的案例
本节为非规范性内容。
ECMAScript 包含一些语法产生式,它们包括“[无 行终止符
这里]”。这些产生式有时是为了在语法中拥有可选操作数。在这些位置引入 行终止符 会通过使用没有可选操作数的语法产生式来改变源文本的语法产生式。
本节的其余部分描述了 ECMAScript 这一版本中使用“[无 行终止符 这里]”的若干产生式。
12.10.3.2.1 带有可选操作数和“[无 行终止符 这里]”的语法产生式列表
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
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 但不是
ReservedWord
注
13.1.2 静态语义:StringValue
语法导向操作
StringValue 不带参数并返回一个字符串。它分段定义在以下生成式中:
IdentifierName
::
IdentifierStart
IdentifierName
IdentifierPart
让 idTextUnescaped 为 IdentifierCodePoints 的
IdentifierName 。
返回 CodePointsToString (idTextUnescaped )。
IdentifierReference
:
yield
BindingIdentifier
:
yield
LabelIdentifier
:
yield
返回 "yield" 。
IdentifierReference
:
await
BindingIdentifier
:
await
LabelIdentifier
:
await
返回 "await" 。
Identifier
:
IdentifierName
但不是 ReservedWord
返回 StringValue 的
IdentifierName 。
PrivateIdentifier
::
#
IdentifierName
返回 0x0023(数字符号)和 StringValue 的
IdentifierName 的 字符串连接 。
ModuleExportName
:
StringLiteral
返回 SV 的 StringLiteral 。
13.1.3 运行时语义:评估
IdentifierReference
:
Identifier
返回 ? ResolveBinding (StringValue 的
Identifier )。
IdentifierReference
:
yield
返回 ? ResolveBinding ("yield" )。
IdentifierReference
:
await
返回 ? ResolveBinding ("await" )。
注 1
注 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 运行时语义:求值
PrimaryExpression
:
this
1. 返回 ? ResolveThisBinding ().
13.2.2 标识符引用
关于IdentifierReference ,请参阅 13.1 。
13.2.3 字面量
语法
Literal
:
NullLiteral
BooleanLiteral
NumericLiteral
StringLiteral
13.2.3.1 运行时语义:求值
Literal
:
NullLiteral
1. 返回 null 。
Literal
:
BooleanLiteral
1. 如果 BooleanLiteral 是标记
false
,返回 false 。
2. 如果 BooleanLiteral 是标记
true
,返回 true 。
Literal
:
NumericLiteral
1. 返回 NumericValue 的 NumericLiteral ,如
12.9.3 中定义。
Literal
:
StringLiteral
1. 返回 SV 的 StringLiteral ,如
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 接受参数 array (一个数组)和 nextIndex (一个整数 )并返回正常完成记录 包含的一个整数 或一个中断完成记录 。它根据以下产生式逐步定义:
Elision
:
,
1. 令 len 为 nextIndex + 1。
2. 执行 ? Set (array , "length" ,𝔽 (len ),
true )。
3. 注意:如果 len 超过 2** 32 - 1,则上述步骤会抛出错误。
4. 返回 len 。
Elision
:
Elision
,
1. 返回 ? ArrayAccumulation of Elision with arguments array
and (nextIndex + 1)。
ElementList
:
Elision opt
AssignmentExpression
1. 如果 Elision 存在,则
a. 设置 nextIndex 为 ? ArrayAccumulation of Elision with arguments
array and nextIndex 。
2. 令 initResult 为 ? Evaluation of AssignmentExpression 。
3. 令 initValue 为 ? GetValue (initResult )。
4. 执行 ! CreateDataPropertyOrThrow (array ,
! ToString (𝔽 (nextIndex )),
initValue )。
5. 返回 nextIndex + 1。
ElementList
:
Elision opt
SpreadElement
1. 如果 Elision 存在,则
a. 设置 nextIndex 为 ? ArrayAccumulation of Elision with arguments
array and nextIndex 。
2. 返回 ? ArrayAccumulation of SpreadElement with arguments
array and nextIndex 。
SpreadElement
:
...
AssignmentExpression
1. 令 spreadRef 为 ? Evaluation of AssignmentExpression 。
2. 令 spreadObj 为 ? GetValue (spreadRef )。
3. 令 iteratorRecord 为 ? GetIterator (spreadObj , sync )。
4. 重复,
a. 令 next 为 ? IteratorStepValue (iteratorRecord )。
b. 如果 next 为 done ,返回
nextIndex 。
c. 执行 ! CreateDataPropertyOrThrow (array ,
! ToString (𝔽 (nextIndex )),
next )。
d. 设置 nextIndex 为 nextIndex + 1。
注
CreateDataPropertyOrThrow
用于确保定义数组的自有属性,即使标准内置数组原型对象 已被修改以阻止使用
[[Set]] 创建新自有属性。
13.2.4.2 运行时语义:求值
ArrayLiteral
:
[
Elision opt
]
1. 令 array 为 ! ArrayCreate (0)。
2. 如果 Elision 存在,则
a. 执行 ? ArrayAccumulation of Elision with arguments
array and 0。
3. 返回 array 。
ArrayLiteral
:
[
ElementList
]
1. 令 array 为 ! ArrayCreate (0)。
2. 执行 ? ArrayAccumulation of ElementList with arguments
array and 0。
3. 返回 array 。
ArrayLiteral
:
[
ElementList
,
Elision opt
]
1. 令 array 为 ! ArrayCreate (0)。
2. 令 nextIndex 为 ? ArrayAccumulation of ElementList with arguments
array and 0。
3. 如果 Elision 存在,则
a. 执行 ? ArrayAccumulation of Elision with arguments
array and nextIndex 。
4. 返回 array 。
13.2.5 对象初始化器
注1
对象初始化器是一个描述对象初始化的表达式,写成类似字面量的形式。它是一个由零个或多个属性键 和关联值组成的列表,用大括号括起来。值不必是字面量;每次对象初始化器求值时,它们都会被求值。
语法
ObjectLiteral [Yield,
Await] :
{
}
{
PropertyDefinitionList [?Yield,
?Await]
}
{
PropertyDefinitionList [?Yield,
?Await]
,
}
PropertyDefinitionList [Yield,
Await] :
PropertyDefinition [?Yield,
?Await]
PropertyDefinitionList [?Yield,
?Await]
,
PropertyDefinition [?Yield,
?Await]
PropertyDefinition [Yield,
Await] :
IdentifierReference [?Yield,
?Await]
CoverInitializedName [?Yield,
?Await]
PropertyName [?Yield,
?Await]
:
AssignmentExpression [+In,
?Yield, ?Await]
MethodDefinition [?Yield,
?Await]
...
AssignmentExpression [+In,
?Yield, ?Await]
PropertyName [Yield,
Await] :
LiteralPropertyName
ComputedPropertyName [?Yield,
?Await]
LiteralPropertyName
:
IdentifierName
StringLiteral
NumericLiteral
ComputedPropertyName [Yield,
Await] :
[
AssignmentExpression [+In,
?Yield, ?Await]
]
CoverInitializedName [Yield,
Await] :
IdentifierReference [?Yield,
?Await]
Initializer [+In, ?Yield,
?Await]
Initializer [In, Yield,
Await] :
=
AssignmentExpression [?In,
?Yield, ?Await]
注2
注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
1. 返回false 。
PropertyName
:
ComputedPropertyName
1. 返回true 。
13.2.5.3 静态语义:PropertyNameList
语法指向操作
PropertyNameList不带参数,返回一个字符串的列表 。它在以下生成中逐段定义:
PropertyDefinitionList
:
PropertyDefinition
1. 让propName 成为PropName of PropertyDefinition 。
2.
如果propName 是empty ,则返回一个新的空列表 。
3. 返回« propName »。
PropertyDefinitionList
:
PropertyDefinitionList
,
PropertyDefinition
1. 让list 成为PropertyNameList
of PropertyDefinitionList 。
2. 让propName 成为PropName of PropertyDefinition 。
3.
如果propName 是empty ,则返回list 。
4. 返回列表连接 of list 和«
propName »。
13.2.5.4 运行时语义:求值
ObjectLiteral
:
{
}
1. 返回OrdinaryObjectCreate (%Object.prototype% )。
ObjectLiteral
:
{
PropertyDefinitionList
}
{
PropertyDefinitionList
,
}
1. 让obj 成为OrdinaryObjectCreate (%Object.prototype% )。
2. 对PropertyDefinitionList 执行PropertyDefinitionEvaluation ,参数为obj 。
3. 返回obj 。
LiteralPropertyName
:
IdentifierName
1. 返回StringValue of
IdentifierName 。
LiteralPropertyName
:
StringLiteral
1. 返回SV of StringLiteral 。
LiteralPropertyName
:
NumericLiteral
1. 让nbr 成为NumericValue of NumericLiteral 。
2. 返回!ToString (nbr )。
ComputedPropertyName
:
[
AssignmentExpression
]
1. 让exprValue 成为Evaluation of AssignmentExpression 。
2. 让propName 成为GetValue (exprValue )。
3. 返回ToPropertyKey (propName )。
13.2.5.5 运行时语义:PropertyDefinitionEvaluation
语法指向操作
PropertyDefinitionEvaluation接受参数object (一个对象)并返回normal completion
containing unused 或一个abrupt
completion 。它在以下生成中逐段定义:
PropertyDefinitionList
:
PropertyDefinitionList
,
PropertyDefinition
1. 对PropertyDefinitionList 执行PropertyDefinitionEvaluation ,参数为object 。
2. 对PropertyDefinition 执行PropertyDefinitionEvaluation ,参数为object 。
3. 返回unused 。
PropertyDefinition
:
...
AssignmentExpression
1. 让exprValue 成为Evaluation of AssignmentExpression 。
2. 让fromValue 成为GetValue (exprValue )。
3. 让excludedNames 成为一个新的空列表 。
4.
对object 、fromValue 和excludedNames 执行CopyDataProperties 。
5. 返回unused 。
PropertyDefinition
:
IdentifierReference
1. 让propName 成为StringValue of
IdentifierReference 。
2. 让exprValue 成为Evaluation of IdentifierReference 。
3. 让propValue 成为GetValue (exprValue )。
4. 断言 :object 是一个普通的、可扩展的对象,没有不可配置的属性。
5.
对object 、propName 和propValue 执行CreateDataPropertyOrThrow 。
6. 返回unused 。
PropertyDefinition
:
PropertyName
:
AssignmentExpression
1. 让propKey 成为Evaluation of PropertyName 。
2. 如果此PropertyDefinition 包含在一个Script 中,并且正在为JSON.parse求值(请参阅7 of JSON.parse ),则
a. 让isProtoSetter 成为false 。
3. 否则,如果propKey 是__proto__ 并且IsComputedPropertyKey
of PropertyName 是false ,则
a. 让isProtoSetter 成为true 。
4. 否则,
a. 让isProtoSetter 成为false 。
5. 如果IsAnonymousFunctionDefinition
of AssignmentExpression 是true 并且isProtoSetter 是false ,则
a. 让propValue 成为NamedEvaluation of AssignmentExpression
with argument propKey 。
6. 否则,
a. 让exprValueRef 成为Evaluation of AssignmentExpression 。
b. 让propValue 成为GetValue (exprValueRef )。
7. 如果isProtoSetter 是true ,则
a. 如果propValue 是一个对象 或propValue 是null ,则
i. 执行!object .[[SetPrototypeOf]] (propValue )。
b. 返回unused 。
8. 断言 :object 是一个普通的、可扩展的对象,没有不可配置的属性。
9.
对object 、propKey 和propValue 执行CreateDataPropertyOrThrow 。
10. 返回unused 。
PropertyDefinition
:
MethodDefinition
1. 对MethodDefinition 执行MethodDefinitionEvaluation ,参数为object 和true 。
2. 返回unused 。
13.2.6 函数定义表达式
参见15.2 了解
PrimaryExpression
: FunctionExpression
。
参见15.5 了解
PrimaryExpression
: GeneratorExpression
。
参见15.7 了解
PrimaryExpression
: ClassExpression
。
参见15.8 了解
PrimaryExpression
: AsyncFunctionExpression
。
参见15.6 了解
PrimaryExpression
: AsyncGeneratorExpression
。
13.2.7 正则表达式字面量
语法
参见12.9.5 。
13.2.7.1 静态语义:早期错误
PrimaryExpression
:
RegularExpressionLiteral
13.2.7.2 静态语义:IsValidRegularExpressionLiteral(literal )
抽象操作IsValidRegularExpressionLiteral接受参数literal (一个RegularExpressionLiteral
Parse
Node )并返回一个布尔值。它在调用时执行以下步骤以确定其参数是否为有效的正则表达式字面量:
1. 令flags 为FlagText 的literal 。
2.
如果flags 包含d
、g
、i
、m
、s
、u
、v
或y
之外的任何代码点,或flags 包含的任何代码点不止一次,则返回false 。
3.
如果flags 包含u
,则令u 为true ;否则令u 为false 。
4.
如果flags 包含v
,则令v 为true ;否则令v 为false 。
5. 令patternText 为BodyText 的literal 。
6.
如果u 为false 且v 为false ,则
a. 令stringValue 为CodePointsToString (patternText )。
b.
将patternText 设置为解释stringValue 的每个16位元素为Unicode
BMP代码点而得到的代码点序列。不对元素应用UTF-16解码。
7. 令parseResult 为ParsePattern (patternText ,
u , v )。
8. 如果parseResult 是一个Parse
Node ,则返回true ;否则返回false 。
13.2.7.3 运行时语义:求值
PrimaryExpression
:
RegularExpressionLiteral
1. 令pattern 为CodePointsToString (BodyText 的RegularExpressionLiteral )。
2. 令flags 为CodePointsToString (FlagText 的RegularExpressionLiteral )。
3. 返回!RegExpCreate (pattern ,
flags )。
13.2.8 模板字面量
语法
TemplateLiteral [Yield,
Await, Tagged] :
NoSubstitutionTemplate
SubstitutionTemplate [?Yield,
?Await, ?Tagged]
SubstitutionTemplate [Yield,
Await, Tagged] :
TemplateHead
Expression [+In, ?Yield,
?Await]
TemplateSpans [?Yield,
?Await, ?Tagged]
TemplateSpans [Yield,
Await, Tagged] :
TemplateTail
TemplateMiddleList [?Yield,
?Await, ?Tagged]
TemplateTail
TemplateMiddleList [Yield,
Await, Tagged] :
TemplateMiddle
Expression [+In, ?Yield,
?Await]
TemplateMiddleList [?Yield,
?Await, ?Tagged]
TemplateMiddle
Expression [+In, ?Yield,
?Await]
13.2.8.1 静态语义: 早期错误
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 静态语义:模板字符串
模板字符串是一个语法导向操作 ,它接受参数raw (一个布尔值)并返回一个
列表 ,其中包含字符串或undefined 。它在以下产生式上分段定义:
TemplateLiteral
: NoSubstitutionTemplate
1. 返回 « TemplateString (NoSubstitutionTemplate ,
raw ) ».
SubstitutionTemplate
:
TemplateHead
Expression
TemplateSpans
1. 设 head 为 « TemplateString (TemplateHead ,
raw ) ».
2. 设 tail 为 TemplateStrings
of TemplateSpans with argument
raw .
3. 返回 head 和 tail 的 列表连接 .
TemplateSpans
: TemplateTail
1. 返回 « TemplateString (TemplateTail ,
raw ) ».
TemplateSpans
:
TemplateMiddleList
TemplateTail
1. 设 middle 为 TemplateStrings
of TemplateMiddleList with
argument raw .
2. 设 tail 为 « TemplateString (TemplateTail ,
raw ) ».
3. 返回 middle 和 tail 的 列表连接 .
TemplateMiddleList
:
TemplateMiddle
Expression
1. 返回 « TemplateString (TemplateMiddle ,
raw ) ».
TemplateMiddleList
:
TemplateMiddleList
TemplateMiddle
Expression
1. 设 front 为 TemplateStrings
of TemplateMiddleList with
argument raw .
2. 设 last 为 « TemplateString (TemplateMiddle ,
raw ) ».
3. 返回 front 和 last 的 列表连接 .
13.2.8.3 静态语义:TemplateString ( templateToken ,
raw )
抽象操作 TemplateString 接受参数 templateToken (一个 NoSubstitutionTemplate
解析节点 ,一个 TemplateHead
解析节点 ,一个 TemplateMiddle
解析节点 ,或一个 TemplateTail
解析节点 )和
raw (一个布尔值),并返回一个字符串或 undefined 。它在被调用时执行以下步骤:
1. 如果 raw 是 true ,则
a. 设 string 为 templateToken 的 TRV 。
2. 否则,
a. 设 string 为 templateToken 的 TV 。
3. 返回 string 。
注
如果 raw 是 false 并且
templateToken 包含一个 NotEscapeSequence ,则此操作返回
undefined 。在所有其他情况下,它返回一个字符串。
13.2.8.4 GetTemplateObject ( templateLiteral )
抽象操作 GetTemplateObject 接受参数 templateLiteral (一个 解析节点 )并返回一个数组。它在被调用时执行以下步骤:
1. 设 realm 为 当前领域记录 。
2. 设 templateRegistry 为 realm .[[TemplateMap]] 。
3. 对于 templateRegistry 中的每个元素 e ,执行
a. 如果 e .[[Site]] 是
与 templateLiteral
相同的解析节点 ,则
i. 返回 e .[[Array]] 。
4. 设 rawStrings 为 TemplateStrings
of templateLiteral with argument true 。
5. 断言 :rawStrings 是一个
字符串列表 。
6. 设 cookedStrings 为 TemplateStrings
of templateLiteral with argument false 。
7. 设 count 为 cookedStrings 的元素数量。
8. 断言 :count ≤ 2** 32 - 1。
9. 设 template 为 ! ArrayCreate (count )。
10. 设 rawObj 为 ! ArrayCreate (count )。
11. 设 index 为 0。
12. 重复,当 index < count 时,
a. 设 prop 为 ! ToString (𝔽 (index ))。
b. 设 cookedValue 为
cookedStrings [index ]。
c. 执行 ! DefinePropertyOrThrow (template ,
prop , PropertyDescriptor { [[Value]] :
cookedValue ,
[[Writable]] : false , [[Enumerable]] : true , [[Configurable]] : false })。
d. 设 rawValue 为字符串值
rawStrings [index ]。
e. 执行 ! DefinePropertyOrThrow (rawObj ,
prop , PropertyDescriptor { [[Value]] : rawValue ,
[[Writable]] : false , [[Enumerable]] : true , [[Configurable]] : false })。
f. 设 index 为 index + 1。
13. 执行 ! SetIntegrityLevel (rawObj ,
frozen )。
14. 执行 ! DefinePropertyOrThrow (template ,
"raw" , PropertyDescriptor { [[Value]] :
rawObj ,
[[Writable]] : false , [[Enumerable]] : false , [[Configurable]] : false })。
15. 执行 ! SetIntegrityLevel (template ,
frozen )。
16. 将记录 { [[Site]] :
templateLiteral , [[Array]] :
template } 追加到 realm .[[TemplateMap]] 。
17. 返回 template 。
注 1
注 2
程序代码中的每个 TemplateLiteral
都与一个唯一的模板对象相关联,该对象用于标记模板的求值(13.2.8.6 )。模板对象是冻结的,每次特定标记模板求值时都使用相同的模板对象。模板对象是懒惰创建的(在第一次求值时)还是提前创建的(在第一次求值之前)是实现选择,对
ECMAScript 代码不可见。
注 3
本规范的未来版本可能会定义模板对象的附加不可枚举属性。
13.2.8.5 运行时语义:SubstitutionEvaluation
SubstitutionEvaluation 是一个 语法导向操作 ,它不接受参数,并返回一个
正常完成 包含一个
ECMAScript
语言值列表 或一个 异常完成 。它在以下产生式上分段定义:
TemplateSpans
: TemplateTail
1. 返回一个新的空 列表 。
TemplateSpans
:
TemplateMiddleList
TemplateTail
1. 返回 ? SubstitutionEvaluation of TemplateMiddleList 。
TemplateMiddleList
:
TemplateMiddle
Expression
1. 设 subRef 为 ? Evaluation of Expression 。
2. 设 sub 为 ? GetValue (subRef )。
3. 返回 « sub »。
TemplateMiddleList
:
TemplateMiddleList
TemplateMiddle
Expression
1. 设 preceding 为 ? SubstitutionEvaluation of TemplateMiddleList 。
2. 设 nextRef 为 ? Evaluation of Expression 。
3. 设 next 为 ? GetValue (nextRef )。
4. 返回 preceding 和 « next » 的 列表连接 。
13.2.8.6 运行时语义:求值
TemplateLiteral
: NoSubstitutionTemplate
1. 返回 NoSubstitutionTemplate 的
TV ,定义在 12.9.6 。
SubstitutionTemplate
:
TemplateHead
Expression
TemplateSpans
1. 设 head 为 TemplateHead 的 TV ,定义在
12.9.6 。
2. 设 subRef 为 ? Evaluation of Expression 。
3. 设 sub 为 ? GetValue (subRef )。
4. 设 middle 为 ? ToString (sub )。
5. 设 tail 为 ? Evaluation of TemplateSpans 。
6. 返回 head 、middle 和 tail 的
字符串连接 。
注 1
Expression
值的字符串转换语义类似于 String.prototype.concat
而不是 +
运算符。
TemplateSpans
: TemplateTail
1. 返回 TemplateTail 的 TV ,定义在
12.9.6 。
TemplateSpans
:
TemplateMiddleList
TemplateTail
1. 设 head 为 ? Evaluation of TemplateMiddleList 。
2. 设 tail 为 TemplateTail 的 TV ,定义在
12.9.6 。
3. 返回 head 和 tail 的 字符串连接 。
TemplateMiddleList
:
TemplateMiddle
Expression
1. 设 head 为 TemplateMiddle 的 TV ,定义在
12.9.6 。
2. 设 subRef 为 ? Evaluation of Expression 。
3. 设 sub 为 ? GetValue (subRef )。
4. 设 middle 为 ? ToString (sub )。
5. 返回 head 和 middle 的 字符串连接 。
注 2
Expression
值的字符串转换语义类似于 String.prototype.concat
而不是 +
运算符。
TemplateMiddleList
:
TemplateMiddleList
TemplateMiddle
Expression
1. 设 rest 为 ? Evaluation of TemplateMiddleList 。
2. 设 middle 为 TemplateMiddle 的 TV ,定义在
12.9.6 。
3. 设 subRef 为 ? Evaluation of Expression 。
4. 设 sub 为 ? GetValue (subRef )。
5. 设 last 为 ? ToString (sub )。
6. 返回 rest 、middle 和 last 的
字符串连接 。
注 3
Expression
值的字符串转换语义类似于 String.prototype.concat
而不是 +
运算符。
13.2.9 分组运算符
13.2.9.1 静态语义:早期错误
PrimaryExpression
: CoverParenthesizedExpressionAndArrowParameterList
13.2.9.2 运行时语义:求值
PrimaryExpression
: CoverParenthesizedExpressionAndArrowParameterList
1. 设 expr 为 ParenthesizedExpression
被 覆盖 的 CoverParenthesizedExpressionAndArrowParameterList 。
2. 返回 ? Evaluation
of expr 。
ParenthesizedExpression
:
(
Expression
)
1. 返回 ? Evaluation
of Expression 。这可能是 Reference 类型。
注
此算法不会对 Evaluation of Expression 应用
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]
)
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 > 是评估 StringValue 的
IdentifierName 的结果。
13.3.2.1 运行时语义:评估
MemberExpression
:
MemberExpression
[
Expression
]
1. 设 baseReference 为 ? Evaluation 的 MemberExpression 。
2. 设 baseValue 为 ? GetValue (baseReference )。
3. 如果 源代码匹配
此 MemberExpression 是
严格模式代码 ,设
strict 为 true ;否则设 strict 为
false 。
4. 返回 ? EvaluatePropertyAccessWithExpressionKey (baseValue ,
Expression ,
strict )。
MemberExpression
:
MemberExpression
.
IdentifierName
1. 设 baseReference 为 ? Evaluation 的 MemberExpression 。
2. 设 baseValue 为 ? GetValue (baseReference )。
3. 如果 源代码匹配
此 MemberExpression 是
严格模式代码 ,设
strict 为 true ;否则设 strict 为
false 。
4. 返回 EvaluatePropertyAccessWithIdentifierKey (baseValue ,
IdentifierName ,
strict )。
MemberExpression
:
MemberExpression
.
PrivateIdentifier
1. 设 baseReference 为 ? Evaluation 的 MemberExpression 。
2. 设 baseValue 为 ? GetValue (baseReference )。
3. 设 fieldNameString 为 StringValue 的
PrivateIdentifier 。
4. 返回 MakePrivateReference (baseValue ,
fieldNameString )。
CallExpression
:
CallExpression
[
Expression
]
1. 设 baseReference 为 ? Evaluation 的 CallExpression 。
2. 设 baseValue 为 ? GetValue (baseReference )。
3. 如果 源代码匹配
此 CallExpression 是
严格模式代码 ,设
strict 为 true ;否则设 strict 为
false 。
4. 返回 ? EvaluatePropertyAccessWithExpressionKey (baseValue ,
Expression ,
strict )。
CallExpression
:
CallExpression
.
IdentifierName
1. 设 baseReference 为 ? Evaluation 的 CallExpression 。
2. 设 baseValue 为 ? GetValue (baseReference )。
3. 如果 源代码匹配
此 CallExpression 是
严格模式代码 ,设
strict 为 true ;否则设 strict 为
false 。
4. 返回 EvaluatePropertyAccessWithIdentifierKey (baseValue ,
IdentifierName ,
strict )。
CallExpression
:
CallExpression
.
PrivateIdentifier
1. 设 baseReference 为 ? Evaluation 的 CallExpression 。
2. 设 baseValue 为 ? GetValue (baseReference )。
3. 设 fieldNameString 为 StringValue 的
PrivateIdentifier 。
4. 返回 MakePrivateReference (baseValue ,
fieldNameString )。
13.3.3 EvaluatePropertyAccessWithExpressionKey ( baseValue ,
expression , strict )
抽象操作 EvaluatePropertyAccessWithExpressionKey 接受参数 baseValue (一个
ECMAScript
语言值 ),expression (一个 Expression 解析节点 ),和
strict (一个布尔值),并返回一个 正常完成 包含一个
引用记录 或一个
突然完成 。它在调用时执行以下步骤:
1. 设 propertyNameReference 为 ? Evaluation 的 expression 。
2. 设 propertyNameValue 为 ? GetValue (propertyNameReference )。
3. 设 propertyKey 为 ? ToPropertyKey (propertyNameValue )。
4. 返回 引用记录 { [[Base]] : baseValue , [[ReferencedName]] :
propertyKey , [[Strict]] :
strict , [[ThisValue]] : empty }。
13.3.4 EvaluatePropertyAccessWithIdentifierKey ( baseValue ,
identifierName , strict )
抽象操作 EvaluatePropertyAccessWithIdentifierKey 接受参数 baseValue (一个
ECMAScript
语言值 ),identifierName (一个 IdentifierName 解析节点 ),和
strict (一个布尔值),并返回一个 引用记录 。它在调用时执行以下步骤:
1. 设 propertyNameString 为 StringValue 的
identifierName 。
2. 返回 引用记录 { [[Base]] : baseValue , [[ReferencedName]] :
propertyNameString , [[Strict]] : strict , [[ThisValue]] :
empty }。
13.3.5 The new
Operator
13.3.5.1 运行时语义:评估
NewExpression
:
new
NewExpression
1. 返回 ? EvaluateNew (NewExpression ,
empty )。
MemberExpression
:
new
MemberExpression
Arguments
1. 返回 ? EvaluateNew (MemberExpression , Arguments )。
13.3.5.1.1 EvaluateNew ( constructExpr ,
arguments
)
抽象操作 EvaluateNew 接受参数 constructExpr (一个 NewExpression
解析节点 或一个 MemberExpression 解析节点 )和
arguments (empty 或一个 Arguments 解析节点 ),并返回
一个 正常完成 包含一个
ECMAScript 语言值 或一个
突然完成 。它在调用时执行以下步骤:
1. 设 ref 为 ? Evaluation 的 constructExpr 。
2. 设 constructor 为 ? GetValue (ref )。
3. 如果 arguments 是 empty ,
a. 设 argList 为一个新空的 列表 。
4. 否则,
a. 设 argList 为 ? ArgumentListEvaluation 的 arguments 。
5. 如果 IsConstructor (constructor )
is false ,抛出一个 TypeError 异常。
6. 返回 ? Construct (constructor , argList )。
13.3.6 Function Calls
13.3.6.1 运行时语义:评估
CallExpression
: CoverCallExpressionAndAsyncArrowHead
1. 设 expr 为 CallMemberExpression
被 CoverCallExpressionAndAsyncArrowHead
覆盖的部分。
2. 设 memberExpr 为 expr 的 MemberExpression 。
3. 设 arguments 为 expr 的 Arguments 。
4. 设 ref 为 ? Evaluation 的 memberExpr 。
5. 设 func 为 ? GetValue (ref )。
6. 如果 ref 是一个 引用记录 ,IsPropertyReference (ref )
是 false ,且 ref .[[ReferencedName]] 是
"eval" ,则
a. 如果 SameValue (func ,
%eval% ) 是
true ,则
i. 设 argList 为 ? ArgumentListEvaluation 的 arguments 。
ii. 如果 argList 没有元素,返回
undefined 。
iii. 设 evalArg 为 argList 的第一个元素。
iv. 如果 源代码匹配
此 CallExpression 是
严格模式代码 ,设
strictCaller 为 true 。否则设
strictCaller
为 false 。
v.
返回
? PerformEval (evalArg ,
strictCaller , true )。
7. 设 thisCall 为这个 CallExpression 。
8. 设 tailCall 为 IsInTailPosition (thisCall )。
9. 返回 ? EvaluateCall (func , ref ,
arguments , tailCall )。
一个 CallExpression 评估执行步骤 6.a.v
是一个 直接 eval 。
CallExpression
:
CallExpression
Arguments
1. 设 ref 为 ? Evaluation 的 CallExpression 。
2. 设 func 为 ? GetValue (ref )。
3. 设 thisCall 为这个 CallExpression 。
4. 设 tailCall 为 IsInTailPosition (thisCall )。
5. 返回 ? EvaluateCall (func , ref , Arguments ,
tailCall )。
13.3.6.2 EvaluateCall ( func , ref ,
arguments , tailPosition )
抽象操作 EvaluateCall 接受参数 func (一个 ECMAScript
语言值 ),ref (一个 ECMAScript
语言值 或一个 引用记录 ),arguments (一个
解析节点 ),
tailPosition (一个布尔值),并返回一个 正常完成 包含一个
ECMAScript 语言值 或一个
突然完成 。它在调用时执行以下步骤:
1. 如果 ref 是一个 引用记录 ,则
a. 如果 IsPropertyReference (ref )
是 true ,则
i. 设 thisValue 为 GetThisValue (ref )。
b. 否则,
i. 设 refEnv 为 ref .[[Base]] 。
ii. 断言 :refEnv 是一个
环境记录 。
iii. 设 thisValue 为
refEnv .WithBaseObject()。
2. 否则,
a. 设 thisValue 为 undefined 。
3. 设 argList 为 ? ArgumentListEvaluation 的 arguments 。
4. 如果 func 不是一个对象 ,抛出一个
TypeError 异常。
5. 如果 IsCallable (func ) 是
false ,抛出一个 TypeError 异常。
6. 如果 tailPosition 是 true ,
执行
PrepareForTailCall ()。
7. 返回 ? Call (func ,
thisValue ,
argList )。
13.3.7 The super
关键字
13.3.7.1 运行时语义:评估
SuperProperty
:
super
[
Expression
]
1. 设 env 为运行时执行上下文的 环境记录 。
2. 设 home 为 env .GetSuperBase()。
3. 设 propertyNameReference 为 ? Evaluation 的 表达式 。
4. 设 propertyNameValue 为 ? GetValue (propertyNameReference )。
5. 设 propertyKey 为 ? ToPropertyKey (propertyNameValue )。
6. 设 strict 为 IsStrictReference (propertyNameReference )。
7. 返回 MakeSuperPropertyReference (home ,
propertyKey , strict )。
SuperProperty
:
super
.
IdentifierName
1. 设 env 为运行时执行上下文的 环境记录 。
2. 设 home 为 env .GetSuperBase()。
3. 设 strict 为 IsStrictReference (propertyNameReference )。
4. 设 propertyKey 为 StringValue 的
IdentifierName 。
5. 返回 MakeSuperPropertyReference (home ,
propertyKey , strict )。
SuperCall
:
super
Arguments
1. 设 newTarget 为 GetNewTarget ()。
2. 断言 :newTarget 是一个对象 。
3. 设 func 为 GetSuperConstructor ()。
4. 设 argList 为 ? ArgumentListEvaluation 的 Arguments 。
5. 如果 IsConstructor (func )
是 false ,抛出一个 TypeError 异常。
6. 设 result 为 ? Construct (func , argList ,
newTarget )。
7. 设 thisER 为 GetThisEnvironment ()。
8. 执行
? thisER .BindThisValue(result )。
9. 设 F 为 thisER .[[FunctionObject]] 。
10. 断言 :F 是一个 ECMAScript
函数对象 。
11. 执行 ? InitializeInstanceElements (result ,
F )。
12. 返回 result 。
13.3.7.2 GetSuperConstructor ( )
抽象操作 GetSuperConstructor 不接受任何参数,并返回一个 ECMAScript
语言值 。它在调用时执行以下步骤:
1. 设 envRec 为 GetThisEnvironment ()。
2. 断言 :envRec 是一个
函数环境记录 。
3. 设 activeFunction 为 envRec .[[FunctionObject]] 。
4. 断言 :activeFunction 是一个
ECMAScript 函数对象 。
5. 设 superConstructor 为
! activeFunction .[[GetPrototypeOf]] ()。
6. 返回 superConstructor 。
13.3.7.3 MakeSuperPropertyReference ( actualThis ,
propertyKey , strict )
抽象操作 MakeSuperPropertyReference 接受参数 actualThis (一个 ECMAScript
语言值 ),propertyKey (一个 属性键 ),和
strict (一个布尔值),并返回一个 正常完成 包含一个
Super 引用记录 或一个
抛出完成 。它在调用时执行以下步骤:
1. 设 env 为 GetThisEnvironment ()。
2. 断言 :
env .HasSuperBinding() 是 true 。
3. 设 baseValue 为
? env .GetSuperBase()。
4. 返回 引用记录 {
[[Base]] : baseValue , [[ReferencedName]] :
propertyKey , [[Strict]] :
strict , [[ThisValue]] : actualThis }。
13.3.8 参数列表
注
13.3.8.1 运行时语义:参数列表评估
语法导向操作参数列表评估 不接受参数,并返回一个正常完成 包含一个列表 的
ECMAScript语言值 或一个突然完成 。它在以下产生式上分段定义:
Arguments
:
(
)
1. 返回一个新的空列表 。
ArgumentList
: AssignmentExpression
1. 设ref 为? AssignmentExpression 的评估。
2. 设arg 为? GetValue (ref )。
3. 返回 « arg »。
ArgumentList
:
...
AssignmentExpression
1. 设list 为一个新空列表 。
2. 设spreadRef 为? AssignmentExpression 的评估。
3. 设spreadObj 为? GetValue (spreadRef )。
4. 设iteratorRecord 为? GetIterator (spreadObj ,
sync )。
5. 重复,
a. 设next 为? IteratorStepValue (iteratorRecord )。
b. 如果next 是done ,返回
list 。
c. 将next 添加到list 。
ArgumentList
:
ArgumentList
,
AssignmentExpression
1. 设precedingArgs 为? ArgumentListEvaluation of ArgumentList 。
2. 设ref 为? Evaluation of AssignmentExpression 。
3. 设arg 为? GetValue (ref )。
4. 返回列表连接 of
precedingArgs 和 « arg »。
ArgumentList
:
ArgumentList
,
...
AssignmentExpression
1. 设precedingArgs 为? ArgumentListEvaluation of ArgumentList 。
2. 设spreadRef 为? Evaluation of AssignmentExpression 。
3. 设iteratorRecord 为? GetIterator (? GetValue (spreadRef ),
sync )。
4. 重复,
a. 设next 为? IteratorStepValue (iteratorRecord )。
b. 如果next 是done ,返回
precedingArgs 。
c. 将next 添加到precedingArgs 。
TemplateLiteral
: NoSubstitutionTemplate
1. 设templateLiteral 为这个TemplateLiteral 。
2. 设siteObj 为GetTemplateObject (templateLiteral )。
3. 返回 « siteObj »。
TemplateLiteral
: SubstitutionTemplate
1. 设templateLiteral 为这个TemplateLiteral 。
2. 设siteObj 为GetTemplateObject (templateLiteral )。
3. 设remaining 为? ArgumentListEvaluation of SubstitutionTemplate 。
4. 返回列表连接 of «
siteObj » 和 remaining 。
SubstitutionTemplate
:
TemplateHead
Expression
TemplateSpans
1. 设firstSubRef 为? Evaluation of Expression 。
2. 设firstSub 为? GetValue (firstSubRef )。
3. 设restSub 为? SubstitutionEvaluation of TemplateSpans 。
4. 断言 : restSub 是一个
可能为空的列表 。
5. 返回列表连接 of «
firstSub » 和 restSub 。
13.3.9 可选链
注
一个可选链是一个或多个属性访问和函数调用的链,第一个以?.
标记开始。
13.3.9.1 运行时语义:评估
OptionalExpression
:
MemberExpression
OptionalChain
1. 设baseReference 为? Evaluation of MemberExpression 。
2. 设baseValue 为? GetValue (baseReference )。
3. 如果baseValue 是undefined
或null ,则
a. 返回undefined 。
4. 返回? ChainEvaluation of OptionalChain with arguments
baseValue 和 baseReference 。
OptionalExpression
:
CallExpression
OptionalChain
1. 设baseReference 为? Evaluation of CallExpression 。
2. 设baseValue 为? GetValue (baseReference )。
3. 如果baseValue 是undefined
或null ,则
a. 返回undefined 。
4. 返回? ChainEvaluation of OptionalChain with arguments
baseValue 和 baseReference 。
OptionalExpression
:
OptionalExpression
OptionalChain
1. 设baseReference 为? Evaluation of OptionalExpression 。
2. 设baseValue 为? GetValue (baseReference )。
3. 如果baseValue 是undefined
或null ,则
a. 返回undefined 。
4. 返回? ChainEvaluation of OptionalChain with arguments
baseValue 和 baseReference 。
13.3.9.2 运行时语义:链评估
语法导向操作链评估 接受参数baseValue (一个ECMAScript语言值 )和baseReference (一个ECMAScript语言值 或一个引用记录 ),并返回一个正常完成 ,包含一个ECMAScript语言值 或一个引用记录 ,或一个突然完成 。它在以下产生式上分段定义:
OptionalChain
:
?.
Arguments
1. 设thisChain 为这个OptionalChain 。
2. 设tailCall 为IsInTailPosition (thisChain )。
3. 返回? EvaluateCall (baseValue ,
baseReference ,
Arguments ,
tailCall )。
OptionalChain
:
?.
[
Expression
]
1. 如果这个OptionalChain 的源文本匹配 是严格模式代码 ,设strict 为true ;否则设strict 为false 。
2. 返回? EvaluatePropertyAccessWithExpressionKey (baseValue ,
Expression ,
strict )。
OptionalChain
:
?.
IdentifierName
1. 如果这个OptionalChain 的源文本匹配 是严格模式代码 ,设strict 为true ;否则设strict 为false 。
2. 返回EvaluatePropertyAccessWithIdentifierKey (baseValue ,
IdentifierName ,
strict )。
OptionalChain
:
?.
PrivateIdentifier
1. 设fieldNameString 为PrivateIdentifier 的StringValue 。
2. 返回MakePrivateReference (baseValue ,
fieldNameString )。
OptionalChain
:
OptionalChain
Arguments
1. 设optionalChain 为OptionalChain 。
2. 设newReference 为? ChainEvaluation of optionalChain with arguments
baseValue 和 baseReference 。
3. 设newValue 为? GetValue (newReference )。
4. 设thisChain 为这个OptionalChain 。
5. 设tailCall 为IsInTailPosition (thisChain )。
6. 返回? EvaluateCall (newValue , newReference ,
Arguments ,
tailCall )。
OptionalChain
:
OptionalChain
[
Expression
]
1. 设optionalChain 为OptionalChain 。
2. 设newReference 为? ChainEvaluation of optionalChain with arguments
baseValue 和 baseReference 。
3. 设newValue 为? GetValue (newReference )。
4. 如果这个OptionalChain 的源文本匹配 是严格模式代码 ,设strict 为true ;否则设strict 为false 。
5. 返回? EvaluatePropertyAccessWithExpressionKey (newValue ,
Expression ,
strict )。
OptionalChain
:
OptionalChain
.
IdentifierName
1. 设optionalChain 为OptionalChain 。
2. 设newReference 为? ChainEvaluation of optionalChain with arguments
baseValue 和 baseReference 。
3. 设newValue 为? GetValue (newReference )。
4. 如果这个OptionalChain 的源文本匹配 是严格模式代码 ,设strict 为true ;否则设strict 为false 。
5. 返回EvaluatePropertyAccessWithIdentifierKey (newValue ,
IdentifierName ,
strict )。
OptionalChain
:
OptionalChain
.
PrivateIdentifier
1. 设optionalChain 为OptionalChain 。
2. 设newReference 为? ChainEvaluation of optionalChain with arguments
baseValue 和 baseReference 。
3. 设newValue 为? GetValue (newReference )。
4. 设fieldNameString 为PrivateIdentifier 的StringValue 。
5. 返回MakePrivateReference (newValue ,
fieldNameString )。
13.3.10 Import 调用
13.3.10.1 运行时语义: Evaluation
ImportCall
:
import
(
AssignmentExpression
)
1. 设referrer 为GetActiveScriptOrModule ()。
2. 如果referrer 是null ,设
referrer 为当前领域记录 。
3. 设argRef 为? Evaluation of AssignmentExpression 。
4. 设specifier 为? GetValue (argRef )。
5. 设promiseCapability 为! NewPromiseCapability (%Promise% )。
6. 设specifierString 为Completion (ToString (specifier ))。
7. IfAbruptRejectPromise (specifierString ,
promiseCapability )。
8. 执行HostLoadImportedModule (referrer ,
specifierString , empty , promiseCapability )。
9. 返回promiseCapability .[[Promise]] 。
13.3.10.1.1 ContinueDynamicImport ( promiseCapability ,
moduleCompletion )
抽象操作ContinueDynamicImport接受参数promiseCapability (一个PromiseCapability
Record )和moduleCompletion (一个正常完成 包含一个Module
Record 或一个抛出完成 )并返回unused 。它完成了一个动态导入的原始过程,最初由一个import()
调用启动,根据需要解决或拒绝该调用返回的承诺。它执行以下步骤:
1. 如果moduleCompletion 是一个突然完成 ,则
a. 执行! Call (promiseCapability .[[Reject]] , undefined , «
moduleCompletion .[[Value]] »)。
b. 返回unused 。
2. 设module 为moduleCompletion .[[Value]] 。
3. 设loadPromise 为
module .LoadRequestedModules()。
4. 设rejectedClosure 为一个新抽象闭包 ,参数为(reason ),捕获promiseCapability ,并执行以下步骤:
a. 执行! Call (promiseCapability .[[Reject]] , undefined , « reason »)。
b. 返回unused 。
5. 设onRejected 为CreateBuiltinFunction (rejectedClosure ,
1, "" , « »)。
6. 设linkAndEvaluateClosure 为一个新抽象闭包 ,无参数,捕获module 、promiseCapability 和
onRejected ,并执行以下步骤:
a. 设link 为Completion (module .Link())。
b. 如果link 是一个突然完成 ,则
i. 执行! Call (promiseCapability .[[Reject]] , undefined , « link .[[Value]] »)。
ii. 返回unused 。
c. 设evaluatePromise 为
module .Evaluate()。
d. 设fulfilledClosure 为一个新抽象闭包
,无参数,捕获module 和promiseCapability ,并执行以下步骤:
i. 设namespace 为GetModuleNamespace (module )。
ii. 执行! Call (promiseCapability .[[Resolve]] , undefined , «
namespace »)。
iii. 返回unused 。
e. 设onFulfilled 为CreateBuiltinFunction (fulfilledClosure ,
0, "" , « »)。
f. 执行PerformPromiseThen (evaluatePromise ,
onFulfilled , onRejected )。
g. 返回unused 。
7. 设linkAndEvaluate 为CreateBuiltinFunction (linkAndEvaluateClosure ,
0, "" , « »)。
8. 执行PerformPromiseThen (loadPromise ,
linkAndEvaluate , onRejected )。
9. 返回unused 。
13.3.11 标签模板
注
标签模板是一个函数调用,其中调用的参数是从一个TemplateLiteral
(13.2.8 ) 派生的。实际参数包括一个模板对象
(13.2.8.4 ) 和通过评估嵌入在TemplateLiteral 中的表达式产生的值。
13.3.11.1 运行时语义:评估
MemberExpression
:
MemberExpression
TemplateLiteral
1. 设tagRef 为? Evaluation of MemberExpression 。
2. 设tagFunc 为? GetValue (tagRef )。
3. 设thisCall 为这个MemberExpression 。
4. 设tailCall 为IsInTailPosition (thisCall )。
5. 返回? EvaluateCall (tagFunc , tagRef , TemplateLiteral ,
tailCall )。
CallExpression
:
CallExpression
TemplateLiteral
1. 设tagRef 为? Evaluation of CallExpression 。
2. 设tagFunc 为? GetValue (tagRef )。
3. 设thisCall 为这个CallExpression 。
4. 设tailCall 为IsInTailPosition (thisCall )。
5. 返回? EvaluateCall (tagFunc , tagRef , TemplateLiteral ,
tailCall )。
13.3.12 元属性
13.3.12.1 运行时语义: Evaluation
NewTarget
:
new
.
target
1. 返回 GetNewTarget ()。
ImportMeta
:
import
.
meta
1. 设 module 为 GetActiveScriptOrModule ()。
2. 断言 :module 是一个
源文本模块记录 。
3. 设 importMeta 为 module .[[ImportMeta]] 。
4. 如果 importMeta 是 empty ,
则
a. 设 importMeta 为 OrdinaryObjectCreate (null )。
b. 设 importMetaValues 为 HostGetImportMetaProperties (module )。
c. 对于每个 记录
{ [[Key]] , [[Value]] } p 的
importMetaValues ,执行
i. 执行 ! CreateDataPropertyOrThrow (importMeta ,
p .[[Key]] , p .[[Value]] )。
d. 执行 HostFinalizeImportMeta (importMeta ,
module )。
e. 设 module .[[ImportMeta]]
为 importMeta 。
f. 返回 importMeta 。
5. 否则,
a. 断言 :importMeta
是一个对象 。
b. 返回 importMeta 。
13.3.12.1.1 HostGetImportMetaProperties ( moduleRecord )
The 宿主定义 抽象操作
HostGetImportMetaProperties 接受参数 moduleRecord (一个 模块记录 )并
返回一个 列表 的
记录
带有字段 [[Key]] (一个 属性键 )和 [[Value]] (一个 ECMAScript
语言
值 )。它允许 宿主 提供 属性
键 和值给从 import.meta
返回的对象。
HostGetImportMetaProperties 的默认实现是返回一个新的空 列表 。
13.3.12.1.2 HostFinalizeImportMeta ( importMeta ,
moduleRecord )
The 宿主定义 抽象操作
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 运行时语义:评估
UpdateExpression
:
LeftHandSideExpression
++
1. 设 lhs 为 ? 评估 的 LeftHandSideExpression 。
2. 设 oldValue 为 ? ToNumeric (? GetValue (lhs ))。
3. 如果 oldValue 是一个
数字 ,则
a. 设 newValue 为 Number::add (oldValue ,
1 𝔽 )。
4. 否则,
a. 断言 :oldValue
是一个
大整数 。
b. 设 newValue 为 BigInt::add (oldValue ,
1 ℤ )。
5. 执行 ? PutValue (lhs , newValue )。
6. 返回 oldValue 。
13.4.3 后置递减运算符
13.4.3.1 运行时语义:评估
UpdateExpression
:
LeftHandSideExpression
--
1. 设 lhs 为 ? 评估 的 LeftHandSideExpression 。
2. 设 oldValue 为 ? ToNumeric (? GetValue (lhs ))。
3. 如果 oldValue 是一个
数字 ,则
a. 设 newValue 为 Number::subtract (oldValue ,
1 𝔽 )。
4. 否则,
a. 断言 :oldValue
是一个
大整数 。
b. 设 newValue 为 BigInt::subtract (oldValue ,
1 ℤ )。
5. 执行 ? PutValue (lhs , newValue )。
6. 返回 oldValue 。
13.4.4 前置递增运算符
13.4.4.1 运行时语义:评估
UpdateExpression
:
++
UnaryExpression
1. 设 expr 为 ? 评估 的 UnaryExpression 。
2. 设 oldValue 为 ? ToNumeric (? GetValue (expr ))。
3. 如果 oldValue 是一个
数字 ,则
a. 设 newValue 为 Number::add (oldValue ,
1 𝔽 )。
4. 否则,
a. 断言 :oldValue
是一个
大整数 。
b. 设 newValue 为 BigInt::add (oldValue ,
1 ℤ )。
5. 执行 ? PutValue (expr , newValue )。
6. 返回 newValue 。
13.4.5 前置递减运算符
13.4.5.1 运行时语义:评估
UpdateExpression
:
--
UnaryExpression
1. 设 expr 为 ? 评估 的 UnaryExpression 。
2. 设 oldValue 为 ? ToNumeric (? GetValue (expr ))。
3. 如果 oldValue 是一个
数字 ,则
a. 设 newValue 为 Number::subtract (oldValue ,
1 𝔽 )。
4. 否则,
a. 断言 :oldValue
是一个
大整数 。
b. 设 newValue 为 BigInt::subtract (oldValue ,
1 ℤ )。
5. 执行 ? PutValue (expr , newValue )。
6. 返回 newValue 。
13.5 一元运算符
语法
UnaryExpression [Yield,
Await] :
UpdateExpression [?Yield,
?Await]
delete
UnaryExpression [?Yield,
?Await]
void
UnaryExpression [?Yield,
?Await]
typeof
UnaryExpression [?Yield,
?Await]
+
UnaryExpression [?Yield,
?Await]
-
UnaryExpression [?Yield,
?Await]
~
UnaryExpression [?Yield,
?Await]
!
UnaryExpression [?Yield,
?Await]
[+Await]
AwaitExpression [?Yield]
13.5.1 The delete
运算符
13.5.1.1 静态语义:早期错误
UnaryExpression
:
delete
UnaryExpression
注
最后一项规则意味着表达式如 delete (((foo)))
会产生 早期错误 ,因为递归应用了第一项规则。
13.5.1.2 运行时语义:评估
UnaryExpression
:
delete
UnaryExpression
1. 设 ref 为 ? 评估 的 UnaryExpression 。
2. 如果 ref 不是 引用记录 ,返回
true 。
3. 如果 IsUnresolvableReference (ref )
是 true ,则
a. 断言 :ref .[[Strict]] 是 false 。
b. 返回 true 。
4. 如果 IsPropertyReference (ref )
是 true ,则
a. 断言 :IsPrivateReference (ref )
是 false 。
b. 如果 IsSuperReference (ref )
是 true ,抛出 ReferenceError 异常。
c. 设 baseObj 为
? ToObject (ref .[[Base]] )。
d. 设 deleteStatus 为 ? baseObj .[[Delete]] (ref .[[ReferencedName]] )。
e. 如果 deleteStatus 是 false
并且 ref .[[Strict]] 是 true ,抛出
TypeError 异常。
f. 返回 deleteStatus 。
5. 否则,
a. 设 base 为 ref .[[Base]] 。
b. 断言 :base 是 环境记录 。
c. 返回 ? base .DeleteBinding (ref .[[ReferencedName]] )。
注 1
当 delete
运算符出现在 严格模式代码 中时,如果其 UnaryExpression
是直接引用变量、函数参数或函数名,则抛出 SyntaxError 异常。此外,如果 delete
运算符出现在 严格模式代码 中,并且要删除的属性具有属性 { [[Configurable]] : false }(或无法删除),则抛出
TypeError 异常。
注 2
在步骤 4.c 中可能创建的对象在上述抽象操作和
普通对象 的 [[Delete]] 内部方法之外不可访问。实现可能会选择避免实际创建该对象。
13.5.2 The void
运算符
13.5.2.1 运行时语义:评估
UnaryExpression
:
void
UnaryExpression
1. 设 expr 为 ? 评估 的 UnaryExpression 。
2. 执行 ? GetValue (expr )。
3. 返回 undefined 。
注
GetValue
必须被调用,即使它的值没有被使用,因为它可能有可观察的副作用。
13.5.3 The typeof
运算符
13.5.3.1 运行时语义:评估
UnaryExpression
:
typeof
UnaryExpression
1. 设 val 为 ? 评估 的 UnaryExpression 。
2. 如果 val 是 引用记录 ,则
a. 如果 IsUnresolvableReference (val )
是 true ,返回 "undefined" 。
3. 设 val 为 ? GetValue (val )。
4. 如果 val 是 undefined ,返回
"undefined" 。
5. 如果 val 是 null ,返回
"object" 。
6. 如果 val 是字符串 ,返回
"string" 。
7. 如果 val 是符号 ,返回
"symbol" 。
8. 如果 val 是布尔值 ,返回
"boolean" 。
9. 如果 val 是数字 ,返回
"number" 。
10. 如果 val 是大整数 ,返回
"bigint" 。
11. 断言 :val 是对象 。
12. 注意:这一步在章节 B.3.6.3 中被替换。
13. 如果 val 有 [[Call]]
内部槽,返回 "function" 。
14. 返回 "object" 。
13.5.4 一元 +
运算符
注
13.5.4.1 运行时语义:评估
UnaryExpression
:
+
UnaryExpression
1. 设 expr 为 ? 评估 的 UnaryExpression 。
2. 返回 ? ToNumber (?
GetValue (expr ))。
13.5.5 一元 -
运算符
注
一元 -
运算符将其操作数转换为数值,然后对其取反。取反 +0 𝔽 产生
-0 𝔽 ,取反 -0 𝔽 产生
+0 𝔽 。
13.5.5.1 运行时语义:评估
UnaryExpression
:
-
UnaryExpression
1. 设 expr 为 ? 评估 的 UnaryExpression 。
2. 设 oldValue 为 ? ToNumeric (? GetValue (expr ))。
3. 如果 oldValue 是数字 ,则
a. 返回 Number::unaryMinus (oldValue )。
4. 否则,
a. 断言 :oldValue
是大整数 。
b. 返回 BigInt::unaryMinus (oldValue )。
13.5.6 按位 NOT 运算符 ( ~
)
13.5.6.1 运行时语义:评估
UnaryExpression
:
~
UnaryExpression
1. 设 expr 为 ? 评估 的 UnaryExpression 。
2. 设 oldValue 为 ? ToNumeric (? GetValue (expr ))。
3. 如果 oldValue 是数字 ,则
a. 返回 Number::bitwiseNOT (oldValue )。
4. 否则,
a. 断言 :oldValue
是大整数 。
b. 返回 BigInt::bitwiseNOT (oldValue )。
13.5.7 逻辑 NOT 运算符 ( !
)
13.5.7.1 运行时语义:评估
UnaryExpression
:
!
UnaryExpression
1. 设 expr 为 ? 评估 的 UnaryExpression 。
2. 设 oldValue 为 ToBoolean (?
GetValue (expr ))。
3. 如果 oldValue 是 true ,返回
false 。
4. 返回 true 。
13.6 幂运算符
语法
ExponentiationExpression [Yield,
Await] :
UnaryExpression [?Yield,
?Await]
UpdateExpression [?Yield,
?Await]
**
ExponentiationExpression [?Yield,
?Await]
13.6.1 运行时语义:评估
ExponentiationExpression
:
UpdateExpression
**
ExponentiationExpression
1. 返回 ? EvaluateStringOrNumericBinaryExpression (UpdateExpression ,
**
, ExponentiationExpression ).
13.7 乘法运算符
语法
MultiplicativeExpression [Yield,
Await] :
ExponentiationExpression [?Yield,
?Await]
MultiplicativeExpression [?Yield,
?Await]
MultiplicativeOperator
ExponentiationExpression [?Yield,
?Await]
MultiplicativeOperator
: one of * /
%
注
运算符 *
执行乘法,生成其操作数的乘积。
运算符 /
执行除法,生成其操作数的商。
运算符 %
生成其操作数在隐式除法中的余数。
13.7.1 运行时语义:评估
MultiplicativeExpression
:
MultiplicativeExpression
MultiplicativeOperator
ExponentiationExpression
1. 设 opText 为 源文本匹配的
MultiplicativeOperator 。
2. 返回 ? EvaluateStringOrNumericBinaryExpression (MultiplicativeExpression ,
opText , ExponentiationExpression )。
13.8 加法运算符
语法
AdditiveExpression [Yield,
Await] :
MultiplicativeExpression [?Yield,
?Await]
AdditiveExpression [?Yield,
?Await]
+
MultiplicativeExpression [?Yield,
?Await]
AdditiveExpression [?Yield,
?Await]
-
MultiplicativeExpression [?Yield,
?Await]
13.8.1 加法运算符 ( +
)
注
加法运算符既可以执行字符串连接,也可以执行数值加法。
13.8.1.1 运行时语义:评估
AdditiveExpression
:
AdditiveExpression
+
MultiplicativeExpression
1. 返回 ? EvaluateStringOrNumericBinaryExpression (AdditiveExpression ,
+
, MultiplicativeExpression )。
13.8.2 减法运算符 ( -
)
注
13.8.2.1 运行时语义:评估
AdditiveExpression
:
AdditiveExpression
-
MultiplicativeExpression
1. 返回 ? EvaluateStringOrNumericBinaryExpression (AdditiveExpression ,
-
, MultiplicativeExpression )。
13.9 位移运算符
语法
ShiftExpression [Yield,
Await] :
AdditiveExpression [?Yield,
?Await]
ShiftExpression [?Yield,
?Await]
<<
AdditiveExpression [?Yield,
?Await]
ShiftExpression [?Yield,
?Await]
>>
AdditiveExpression [?Yield,
?Await]
ShiftExpression [?Yield,
?Await]
>>>
AdditiveExpression [?Yield,
?Await]
13.9.1 左移运算符 ( <<
)
注
对左操作数执行按位左移操作,移动的位数由右操作数指定。
13.9.1.1 运行时语义:评估
ShiftExpression
:
ShiftExpression
<<
AdditiveExpression
1. 返回 ? EvaluateStringOrNumericBinaryExpression (ShiftExpression ,
<<
, AdditiveExpression )。
13.9.2 带符号右移运算符 ( >>
)
注
对左操作数执行按位右移操作,移动的位数由右操作数指定,并使用符号位填充空出的位。
13.9.2.1 运行时语义:评估
ShiftExpression
:
ShiftExpression
>>
AdditiveExpression
1. 返回 ? EvaluateStringOrNumericBinaryExpression (ShiftExpression ,
>>
, AdditiveExpression )。
13.9.3 无符号右移运算符 ( >>>
)
注
对左操作数执行按位右移操作,移动的位数由右操作数指定,并使用零填充空出的位。
13.9.3.1 运行时语义:评估
ShiftExpression
:
ShiftExpression
>>>
AdditiveExpression
1. 返回 ? EvaluateStringOrNumericBinaryExpression (ShiftExpression ,
>>>
, AdditiveExpression )。
13.10 关系运算符
注 1
关系运算符的求值结果总是布尔类型,反映运算符命名的关系是否在其两个操作数之间成立。
语法
RelationalExpression
[In, Yield, Await]
:
ShiftExpression
[?Yield, ?Await]
RelationalExpression
[?In, ?Yield, ?Await]
<
ShiftExpression
[?Yield, ?Await]
RelationalExpression
[?In, ?Yield, ?Await]
>
ShiftExpression
[?Yield, ?Await]
RelationalExpression
[?In, ?Yield, ?Await]
<=
ShiftExpression
[?Yield, ?Await]
RelationalExpression
[?In, ?Yield, ?Await]
>=
ShiftExpression
[?Yield, ?Await]
RelationalExpression
[?In, ?Yield, ?Await]
instanceof
ShiftExpression
[?Yield, ?Await]
[+In]
RelationalExpression
[+In, ?Yield, ?Await]
in
ShiftExpression
[?Yield, ?Await]
[+In]
PrivateIdentifier
in
ShiftExpression
[?Yield, ?Await]
注 2
[In] 语法参数是为了避免在关系表达式中混淆 in
运算符和 for
语句中的 in
运算符。
13.10.1 运行时语义: 求值
RelationalExpression
:
RelationalExpression
<
ShiftExpression
1. 让 lref 为 ?
Evaluation
of
RelationalExpression
。
2. 让 lval 为 ?
GetValue
(lref )。
3. 让 rref 为 ?
Evaluation
of
ShiftExpression
。
4. 让 rval 为 ?
GetValue
(rref )。
5. 让 r 为 ?
IsLessThan
(lval , rval , true )。
6. 如果 r 是 undefined ,返回
false 。否则,返回 r 。
RelationalExpression
:
RelationalExpression
>
ShiftExpression
1. 让 lref 为 ?
Evaluation
of
RelationalExpression
。
2. 让 lval 为 ?
GetValue
(lref )。
3. 让 rref 为 ?
Evaluation
of
ShiftExpression
。
4. 让 rval 为 ?
GetValue
(rref )。
5. 让 r 为 ?
IsLessThan
(rval , lval , false )。
6. 如果 r 是 undefined ,返回
false 。否则,返回 r 。
RelationalExpression
:
RelationalExpression
<=
ShiftExpression
1. 让 lref 为 ?
Evaluation
of
RelationalExpression
。
2. 让 lval 为 ?
GetValue
(lref )。
3. 让 rref 为 ?
Evaluation
of
ShiftExpression
。
4. 让 rval 为 ?
GetValue
(rref )。
5. 让 r 为 ?
IsLessThan
(rval , lval , false )。
6. 如果 r 是 true 或
undefined ,返回 false 。否则,返回 true 。
RelationalExpression
:
RelationalExpression
>=
ShiftExpression
1. 让 lref 为 ?
Evaluation
of
RelationalExpression
。
2. 让 lval 为 ?
GetValue
(lref )。
3. 让 rref 为 ?
Evaluation
of
ShiftExpression
。
4. 让 rval 为 ?
GetValue
(rref )。
5. 让 r 为 ?
IsLessThan
(lval , rval , true )。
6. 如果 r 是 true 或
undefined ,返回 false 。否则,返回 true 。
RelationalExpression
:
RelationalExpression
instanceof
ShiftExpression
1. 让 lref 为 ?
Evaluation
of
RelationalExpression
。
2. 让 lval 为 ?
GetValue
(lref )。
3. 让 rref 为 ?
Evaluation
of
ShiftExpression
。
4. 让 rval 为 ?
GetValue
(rref )。
5. 返回 ?
InstanceofOperator
(lval , rval )。
RelationalExpression
:
RelationalExpression
in
ShiftExpression
1. 让 lref 为 ?
Evaluation
of
RelationalExpression
。
2. 让 lval 为 ?
GetValue
(lref )。
3. 让 rref 为 ?
Evaluation
of
ShiftExpression
。
4. 让 rval 为 ?
GetValue
(rref )。
5. 如果 rval
不是对象
,抛出 TypeError 异常。
6. 返回 ?
HasProperty
(rval ,?
ToPropertyKey
(lval ))。
RelationalExpression
:
PrivateIdentifier
in
ShiftExpression
1. 让 privateIdentifier 为
StringValue
of
PrivateIdentifier
。
2. 让 rref 为 ?
Evaluation
of
ShiftExpression
。
3. 让 rval 为 ?
GetValue
(rref )。
4. 如果 rval
不是对象
,抛出 TypeError 异常。
5. 让 privateEnv 为
运行执行上下文
的 PrivateEnvironment。
6. 让 privateName 为
ResolvePrivateIdentifier
(privateEnv ,privateIdentifier )。
7. 如果
PrivateElementFind
(rval ,privateName ) 不是 empty ,返回
true 。
8. 返回 false 。
13.10.2 InstanceofOperator ( V , target )
抽象操作 InstanceofOperator 接受参数 V (一个
ECMAScript 语言值
)和 target (一个
ECMAScript 语言值
)并返回一个包含布尔值或抛出完成记录的
正常完成
记录。它实现了一个通用算法,用于确定 V 是否是 target 的实例,方法是咨询
target 的
@@hasInstance
方法,或者在没有这种方法的情况下,确定 target 的 "prototype" 属性的值是否存在于 V 的原型链中。调用时执行以下步骤:
1. 如果 target
不是对象
,抛出 TypeError 异常。
2. 让 instOfHandler 为 ?
GetMethod
(target ,
@@hasInstance
)。
3. 如果 instOfHandler 不是
undefined ,则
a. 返回
ToBoolean
(?
Call
(instOfHandler ,target ,« V »))。
4. 如果
IsCallable
(target ) 是 false ,抛出 TypeError 异常。
5. 返回 ?
OrdinaryHasInstance
(target ,V )。
注
步骤
4
和
5
提供了与以前版本的 ECMAScript 的兼容性,这些版本没有使用
@@hasInstance
方法来定义 instanceof
运算符语义。如果对象没有定义或继承
@@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 运行时语义:求值
EqualityExpression
:
EqualityExpression
==
RelationalExpression
1. 让 lref 为 ?
Evaluation
of
EqualityExpression
。
2. 让 lval 为 ?
GetValue
(lref )。
3. 让 rref 为 ?
Evaluation
of
RelationalExpression
。
4. 让 rval 为 ?
GetValue
(rref )。
5. 返回 ?
IsLooselyEqual
(rval , lval )。
EqualityExpression
:
EqualityExpression
!=
RelationalExpression
1. 让 lref 为 ?
Evaluation
of
EqualityExpression
。
2. 让 lval 为 ?
GetValue
(lref )。
3. 让 rref 为 ?
Evaluation
of
RelationalExpression
。
4. 让 rval 为 ?
GetValue
(rref )。
5. 让 r 为 ?
IsLooselyEqual
(rval , lval )。
6. 如果 r 是 true ,返回
false 。否则,返回 true 。
EqualityExpression
:
EqualityExpression
===
RelationalExpression
1. 让 lref 为 ?
Evaluation
of
EqualityExpression
。
2. 让 lval 为 ?
GetValue
(lref )。
3. 让 rref 为 ?
Evaluation
of
RelationalExpression
。
4. 让 rval 为 ?
GetValue
(rref )。
5. 返回
IsStrictlyEqual
(rval , lval )。
EqualityExpression
:
EqualityExpression
!==
RelationalExpression
1. 让 lref 为 ?
Evaluation
of
EqualityExpression
。
2. 让 lval 为 ?
GetValue
(lref )。
3. 让 rref 为 ?
Evaluation
of
RelationalExpression
。
4. 让 rval 为 ?
GetValue
(rref )。
5. 让 r 为
IsStrictlyEqual
(rval , lval )。
6. 如果 r 是 true ,返回
false 。否则,返回 true 。
注 1
根据上述等值定义:
字符串比较可以通过:`${a}` == `${b}`
强制进行。
数字比较可以通过:+a == +b
强制进行。
布尔值比较可以通过:!a == !b
强制进行。
注 2
等值运算符保持以下不变量:
A != B
等价于 !(A == B)
。
A == B
等价于 B == A
,除了 A
和 B
的求值顺序。
注 3
等值运算符并不总是传递的。例如,可能存在两个不同的字符串对象,每个对象表示相同的字符串值;每个字符串对象会被 ==
运算符视为与字符串值相等,但这两个字符串对象彼此并不相等。例如:
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 运行时语义:求值
BitwiseANDExpression
:
BitwiseANDExpression
&
EqualityExpression
1. 返回 ?
EvaluateStringOrNumericBinaryExpression
(
BitwiseANDExpression
, &
,
EqualityExpression
)。
BitwiseXORExpression
:
BitwiseXORExpression
^
BitwiseANDExpression
1. 返回 ?
EvaluateStringOrNumericBinaryExpression
(
BitwiseXORExpression
, ^
,
BitwiseANDExpression
)。
BitwiseORExpression
:
BitwiseORExpression
|
BitwiseXORExpression
1. 返回 ?
EvaluateStringOrNumericBinaryExpression
(
BitwiseORExpression
, |
,
BitwiseXORExpression
)。
13.13 二进制逻辑运算符
语法
LogicalANDExpression
[In, Yield, Await]
:
BitwiseORExpression
[?In, ?Yield, ?Await]
LogicalANDExpression
[?In, ?Yield, ?Await]
&&
BitwiseORExpression
[?In, ?Yield, ?Await]
LogicalORExpression
[In, Yield, Await]
:
LogicalANDExpression
[?In, ?Yield, ?Await]
LogicalORExpression
[?In, ?Yield, ?Await]
||
LogicalANDExpression
[?In, ?Yield, ?Await]
CoalesceExpression
[In, Yield, Await]
:
CoalesceExpressionHead
[?In, ?Yield, ?Await]
??
BitwiseORExpression
[?In, ?Yield, ?Await]
CoalesceExpressionHead
[In, Yield, Await]
:
CoalesceExpression
[?In, ?Yield, ?Await]
BitwiseORExpression
[?In, ?Yield, ?Await]
ShortCircuitExpression
[In, Yield, Await]
:
LogicalORExpression
[?In, ?Yield, ?Await]
CoalesceExpression
[?In, ?Yield, ?Await]
注
由 &&
或 ||
运算符生成的值不一定是布尔类型。生成的值始终是两个操作数表达式之一的值。
13.13.1 运行时语义:求值
LogicalANDExpression
:
LogicalANDExpression
&&
BitwiseORExpression
1. 令 lref 为 ?
Evaluation
of
LogicalANDExpression
。
2. 令 lval 为 ?
GetValue
(lref )。
3. 令 lbool 为
ToBoolean
(lval )。
4. 如果 lbool 为 false ,则返回 lval 。
5. 令 rref 为 ?
Evaluation
of
BitwiseORExpression
。
6. 返回 ?
GetValue
(rref )。
LogicalORExpression
:
LogicalORExpression
||
LogicalANDExpression
1. 令 lref 为 ?
Evaluation
of
LogicalORExpression
。
2. 令 lval 为 ?
GetValue
(lref )。
3. 令 lbool 为
ToBoolean
(lval )。
4. 如果 lbool 为 true ,则返回 lval 。
5. 令 rref 为 ?
Evaluation
of
LogicalANDExpression
。
6. 返回 ?
GetValue
(rref )。
CoalesceExpression
:
CoalesceExpressionHead
??
BitwiseORExpression
1. 令 lref 为 ?
Evaluation
of
CoalesceExpressionHead
。
2. 令 lval 为 ?
GetValue
(lref )。
3. 如果 lval 是 undefined 或
null ,则
a. 令 rref 为 ?
Evaluation
of
BitwiseORExpression
。
b. 返回 ?
GetValue
(rref )。
4. 否则,
a. 返回 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 中的稍有不同。C 和 Java 允许第二个子表达式是一个
Expression
,但限制第三个表达式为
ConditionalExpression
。ECMAScript 这样设计的动机是允许赋值表达式由条件的任意一边控制,并且消除在中间表达式中出现逗号表达式这一困惑且几乎无用的情况。
13.14.1 运行时语义:求值
ConditionalExpression
:
ShortCircuitExpression
?
AssignmentExpression
:
AssignmentExpression
1. 令 lref 为 ?
Evaluation
of
ShortCircuitExpression
。
2. 令 lval 为
ToBoolean
(?
GetValue
(lref ))。
3. 如果 lval 为 true ,则
a. 令 trueRef 为 ?
Evaluation
of 第一个
AssignmentExpression
。
b. 返回 ?
GetValue
(trueRef )。
4. 否则,
a. 令 falseRef 为 ?
Evaluation
of 第二个
AssignmentExpression
。
b. 返回 ?
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
如果
LeftHandSideExpression
是
ObjectLiteral
或
ArrayLiteral
,则应用以下早期错误规则:
如果
LeftHandSideExpression
既不是
ObjectLiteral
也不是
ArrayLiteral
,则应用以下早期错误规则:
AssignmentExpression
:
LeftHandSideExpression
AssignmentOperator
AssignmentExpression
LeftHandSideExpression
&&=
AssignmentExpression
LeftHandSideExpression
||=
AssignmentExpression
LeftHandSideExpression
??=
AssignmentExpression
13.15.2 运行时语义:求值
AssignmentExpression
:
LeftHandSideExpression
=
AssignmentExpression
1. 如果
LeftHandSideExpression
既不是
ObjectLiteral
也不是
ArrayLiteral
,则:
a. 让
lref 是对
Evaluation
的
LeftHandSideExpression
的求值。
b. 如果
IsAnonymousFunctionDefinition
(
AssignmentExpression
)和
IsIdentifierRef
的
LeftHandSideExpression
都为true ,则:
i. 让
rval 是对
NamedEvaluation
(
AssignmentExpression
),带有参数lref .[[ReferencedName]] 。
c. 否则,
i. 让
rref 是对
Evaluation
(
AssignmentExpression
)的求值。
ii. 让
rval 是对
GetValue
(rref )的求值。
d. 执行
PutValue
(
lref ,rval )。
e. 返回rval 。
2. 让
assignmentPattern 成为
AssignmentPattern
,由
涵盖
的
LeftHandSideExpression
。
3. 让
rref 是对
Evaluation
(
AssignmentExpression
)的求值。
4. 让
rval 是对
GetValue
(rref )的求值。
5. 执行
DestructuringAssignmentEvaluation
的assignmentPattern ,带有参数rval 。
6. 返回rval 。
AssignmentExpression
:
LeftHandSideExpression
AssignmentOperator
AssignmentExpression
1. 让
lref 是对
Evaluation
的
LeftHandSideExpression
的求值。
2. 让
lval 是对
GetValue
(lref )的求值。
3. 让
rref 是对
Evaluation
的
AssignmentExpression
的求值。
4. 让
rval 是对
GetValue
(rref )的求值。
5. 让
assignmentOpText 是
源文本匹配
的
AssignmentOperator
。
6. 让
opText 成为以下表格中与assignmentOpText 关联的Unicode代码点序列:
assignmentOpText
opText
**=
**
*=
*
/=
/
%=
%
+=
+
-=
-
<<=
<<
>>=
>>
>>>=
>>>
&=
&
^=
^
|=
|
7. 让
r 是对
ApplyStringOrNumericBinaryOperator
(
lval ,
opText ,
rval )的求值。
8. 执行
PutValue
(
lref ,
r )。
9. 返回r 。
AssignmentExpression
:
LeftHandSideExpression
&&=
AssignmentExpression
1. 让
lref 是对
Evaluation
的
LeftHandSideExpression
的求值。
2. 让
lval 是对
GetValue
(lref )的求值。
3. 让
lbool 是
ToBoolean
(lval )的求值。
4. 如果lbool 为false ,返回lval 。
5. 如果
IsAnonymousFunctionDefinition
(
AssignmentExpression
)为
true ,且
IsIdentifierRef
的
LeftHandSideExpression
为true ,则:
a. 让
rval 是对
NamedEvaluation
(
AssignmentExpression
),带有参数
lref .[[ReferencedName]] 。
6. 否则,
a. 让
rref 是对
Evaluation
的
AssignmentExpression
的求值。
b. 让
rval 是对
GetValue
(rref )的求值。
7. 执行
PutValue
(
lref ,rval )。
8. 返回rval 。
AssignmentExpression
:
LeftHandSideExpression
||=
AssignmentExpression
1. 让
lref 是对
Evaluation
的
LeftHandSideExpression
的求值。
2. 让
lval 是对
GetValue
(lref )的求值。
3. 让
lbool 是
ToBoolean
(lval )的求值。
4. 如果lbool 为true ,返回lval 。
5. 如果
IsAnonymousFunctionDefinition
(
AssignmentExpression
)为
true ,且
IsIdentifierRef
的
LeftHandSideExpression
为true ,则:
a. 让
rval 是对
NamedEvaluation
(
AssignmentExpression
),带有参数
lref .[[ReferencedName]] 。
6. 否则,
a. 让
rref 是对
Evaluation
的
AssignmentExpression
的求值。
b. 让
rval 是对
GetValue
(rref )的求值。
7. 执行
PutValue
(
lref ,rval )。
8. 返回rval 。
AssignmentExpression
:
LeftHandSideExpression
??=
AssignmentExpression
1. 让
lref 是对
Evaluation
的
LeftHandSideExpression
的求值。
2. 让
lval 是对
GetValue
(lref )的求值。
3. 如果
lval 既不是undefined 也不是null ,返回
lval 。
4. 如果
IsAnonymousFunctionDefinition
(
AssignmentExpression
)为
true ,且
IsIdentifierRef
的
LeftHandSideExpression
为true ,则:
a. 让
rval 是对
NamedEvaluation
(
AssignmentExpression
),带有参数
lref .[[ReferencedName]] 。
5. 否则,
a. 让
rref 是对
Evaluation
的
AssignmentExpression
的求值。
b. 让
rval 是对
GetValue
(rref )的求值。
6. 执行
PutValue
(
lref ,rval )。
7. 返回rval 。
注
当此表达式出现在
严格模式代码
中时,如果步骤
1.d
、
2
、
2
、
2
、
2
中的
lref 是不可解析的引用,则会抛出ReferenceError 异常。此外,如果
lref 在步骤
8
、
7
、
7
、
6
中引用了具有属性值{[[Writable]] :false }的数据属性、属性值{[[Set]] :undefined }的访问器属性或对于其
IsExtensible
谓词返回值为false 的对象的不存在属性,在这些情况下,会抛出TypeError 异常。
13.15.3 ApplyStringOrNumericBinaryOperator ( lval ,
opText , rval )
抽象操作 ApplyStringOrNumericBinaryOperator 接受参数 lval (一个 ECMAScript
语言值 )、opText (**
、*
、/
、%
、+
、-
、<<
、>>
、>>>
、&
、^
或 |
)和 rval (一个 ECMAScript 语言值 ),并返回一个
正常完成记录,包含 一个字符串、一个
BigInt 或一个数字,或者一个 抛出完成 。调用时执行以下步骤:
1. 如果 opText 是 +
,则
a. 令 lprim 为 ? ToPrimitive (lval )。
b. 令 rprim 为 ? ToPrimitive (rval )。
c. 如果 lprim 是 字符串 或
rprim 是 字符串 ,则
i. 令 lstr 为 ? ToString (lprim )。
ii. 令 rstr 为 ? ToString (rprim )。
iii. 返回 lstr 和 rstr 的 字符串连接 。
d. 将 lval 设置为 lprim 。
e. 将 rval 设置为 rprim 。
2. 注意:此时,它必须是一个数值运算。
3. 令 lnum 为 ? ToNumeric (lval )。
4. 令 rnum 为 ? ToNumeric (rval )。
5. 如果 lnum 的 类型 与
rnum 的 类型 不同,抛出一个
TypeError 异常。
6. 如果 lnum 是 BigInt ,则
a. 如果 opText 是 **
,返回 ? BigInt::exponentiate (lnum ,
rnum )。
b. 如果 opText 是 /
,返回 ? BigInt::divide (lnum ,
rnum )。
c. 如果 opText 是 %
,返回 ? BigInt::remainder (lnum ,
rnum )。
d. 如果 opText 是 >>>
,返回
? BigInt::unsignedRightShift (lnum ,
rnum )。
7. 令 operation 为与以下表格中的 opText 和 lnum 的
类型 相关的抽象操作:
8. 返回 operation (lnum , rnum )。
注 1
在步骤 ToPrimitive
中没有提供提示。除了日期对象之外,所有标准对象在没有提示的情况下都将其处理为 number ;日期对象在没有提示的情况下将其处理为
string 。特殊对象 可能以其他方式处理没有提示的情况。
注 2
步骤 1.c 与算法 IsLessThan 的步骤 3 不同,使用逻辑或运算而不是逻辑与运算。
13.15.4 EvaluateStringOrNumericBinaryExpression ( leftOperand ,
opText , rightOperand )
抽象操作 EvaluateStringOrNumericBinaryExpression 接受参数 leftOperand (一个解析节点 )、opText (一个 Unicode
代码点序列)和 rightOperand (一个解析节点 ),返回一个正常完成记录 ,其中包含一个字符串、BigInt
或数字,或者一个中断完成记录 。当被调用时,它执行以下步骤:
1. 让 lref 为 ? Evaluation 的 leftOperand 。
2. 让 lval 为 ? GetValue (lref )。
3. 让 rref 为 ? Evaluation 的 rightOperand 。
4. 让 rval 为 ? GetValue (rref )。
5. 返回 ? ApplyStringOrNumericBinaryOperator (lval ,
opText , rval )。
13.15.5 解构赋值
补充语法
在处理以下产生式的实例时
AssignmentExpression
:
LeftHandSideExpression
=
AssignmentExpression
对于 LeftHandSideExpression
的解释将使用以下语法进行细化:
AssignmentPattern [Yield,
Await] :
ObjectAssignmentPattern [?Yield,
?Await]
ArrayAssignmentPattern [?Yield,
?Await]
ObjectAssignmentPattern [Yield,
Await] :
{
}
{
AssignmentRestProperty [?Yield,
?Await]
}
{
AssignmentPropertyList [?Yield,
?Await]
}
{
AssignmentPropertyList [?Yield,
?Await]
,
AssignmentRestProperty [?Yield,
?Await] opt
}
ArrayAssignmentPattern [Yield,
Await] :
[
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
如果 LeftHandSideExpression
是 ObjectLiteral 或 ArrayLiteral ,则适用以下早期错误规则:
如果 LeftHandSideExpression
既不是 ObjectLiteral 也不是 ArrayLiteral ,则适用以下早期错误规则:
13.15.5.2 运行时语义:DestructuringAssignmentEvaluation
语法指引操作
DestructuringAssignmentEvaluation 接受参数 value (一个
ECMAScript 语言值
)并返回一个包含
正常完成
的 unused 或一个
突然完成
。它通过以下生成规则分段定义:
ObjectAssignmentPattern
:
{
}
执行 ?
RequireObjectCoercible
(value )。
返回 unused 。
ObjectAssignmentPattern
:
{
AssignmentPropertyList
}
{
AssignmentPropertyList
,
}
执行 ?
RequireObjectCoercible
(value )。
执行 ?
PropertyDestructuringAssignmentEvaluation
of
AssignmentPropertyList
with argument value 。
返回 unused 。
ObjectAssignmentPattern
:
{
AssignmentRestProperty
}
执行 ?
RequireObjectCoercible
(value )。
让 excludedNames 成为一个新的空的
列表
。
返回 ?
RestDestructuringAssignmentEvaluation
of
AssignmentRestProperty
with arguments value 和 excludedNames 。
ObjectAssignmentPattern
:
{
AssignmentPropertyList
,
AssignmentRestProperty
}
执行 ?
RequireObjectCoercible
(value )。
让 excludedNames 成为 ?
PropertyDestructuringAssignmentEvaluation
of
AssignmentPropertyList
with argument value 。
返回 ?
RestDestructuringAssignmentEvaluation
of
AssignmentRestProperty
with arguments value 和 excludedNames 。
ArrayAssignmentPattern
:
[
]
让 iteratorRecord 成为 ?
GetIterator
(value , sync )。
返回 ?
IteratorClose
(iteratorRecord ,
NormalCompletion
(unused ))。
ArrayAssignmentPattern
:
[
Elision
]
让 iteratorRecord 成为 ?
GetIterator
(value , sync )。
让 result 成为
Completion
(
IteratorDestructuringAssignmentEvaluation
of
Elision
with argument iteratorRecord )。
如果 iteratorRecord .[[Done]] 为 false ,返回 ?
IteratorClose
(iteratorRecord , result )。
返回 result 。
ArrayAssignmentPattern
:
[
Elision opt
AssignmentRestElement
]
让 iteratorRecord 成为 ?
GetIterator
(value , sync )。
如果 Elision
存在,则
让 status 成为
Completion
(
IteratorDestructuringAssignmentEvaluation
of
Elision
with argument iteratorRecord )。
如果 status 是一个
突然完成
,则
断言 :
iteratorRecord .[[Done]] 为 true 。
返回 ? status 。
让 result 成为
Completion
(
IteratorDestructuringAssignmentEvaluation
of
AssignmentRestElement
with argument iteratorRecord )。
如果 iteratorRecord .[[Done]] 为 false ,返回 ?
IteratorClose
(iteratorRecord , result )。
返回 result 。
ArrayAssignmentPattern
:
[
AssignmentElementList
,
Elision opt
AssignmentRestElement opt
]
让 iteratorRecord 成为 ?
GetIterator
(value , sync )。
让 status 成为
Completion
(
IteratorDestructuringAssignmentEvaluation
of AssignmentElementList
with argument iteratorRecord )。
如果 status 是一个
突然完成
,则
如果 iteratorRecord .[[Done]] 为 false ,返回 ?
IteratorClose
(iteratorRecord , status )。
返回 ? status 。
如果 Elision
存在,则
设置 status 为
Completion
(
IteratorDestructuringAssignmentEvaluation
of Elision with argument
iteratorRecord )。
如果 status 是一个
突然完成
,则
断言 :
iteratorRecord .[[Done]] 为 true 。
返回 ? status 。
如果 AssignmentRestElement
存在,则
设置 status 为
Completion
(
IteratorDestructuringAssignmentEvaluation
of AssignmentRestElement
with argument iteratorRecord )。
如果 iteratorRecord .[[Done]] 为 false ,返回 ?
IteratorClose
(iteratorRecord , status )。
返回 ? status 。
13.15.5.3 运行时语义:属性解构赋值求值
语法导向操作 PropertyDestructuringAssignmentEvaluation
接受参数 value
(一个
ECMAScript 语言值 ),并返回一个
包含 的正常完成
属性键列表 或一个
异常完成 。它收集所有解构的
属性键 。它的定义如下:
AssignmentPropertyList
:
AssignmentPropertyList
,
AssignmentProperty
1. 让 propertyNames 是 ? PropertyDestructuringAssignmentEvaluation 对 AssignmentPropertyList
调用时的参数 value 。
2. 让 nextNames 是 ? PropertyDestructuringAssignmentEvaluation 对 AssignmentProperty 调用时的参数
value 。
3. 返回 propertyNames 和 nextNames 的 列表连接 。
AssignmentProperty
:
IdentifierReference
Initializer opt
1. 让 P 是 StringValue
的 IdentifierReference 。
2. 让 lref 是 ? ResolveBinding (P )。
3. 让 v 是 ? GetV (value , P )。
4. 如果 Initializer 存在并且
v 是 undefined ,则
a. 如果 IsAnonymousFunctionDefinition (Initializer )
为
true ,则
i. 将 v 设置为 ? NamedEvaluation 的 Initializer 参数为
P 。
b. 否则,
i. 让 defaultValue 是 ? Evaluation 的 Initializer 。
ii. 将 v 设置为 ? GetValue (defaultValue )。
5. 执行 ? PutValue (lref , v )。
6. 返回 « P »。
AssignmentProperty
:
PropertyName
:
AssignmentElement
1. 让 name 是 ? Evaluation 的 PropertyName 。
2. 执行 ? KeyedDestructuringAssignmentEvaluation 的 AssignmentElement 参数为
value 和 name 。
3. 返回 « name »。
13.15.5.4 运行时语义:RestDestructuringAssignmentEvaluation
语法导向操作 RestDestructuringAssignmentEvaluation
接受参数 value
(一个
ECMAScript 语言值 ) 和
excludedNames (一个
列表 的
属性键 ),并返回一个
包含
unused 的正常完成记录,或一个
异常完成 。它的定义如下:
AssignmentRestProperty
:
...
DestructuringAssignmentTarget
1. 让 lref 是 ? Evaluation 的 DestructuringAssignmentTarget 。
2. 让 restObj 是 OrdinaryObjectCreate (%Object.prototype% )。
3. 执行 ? CopyDataProperties (restObj , value ,
excludedNames )。
4. 返回 ? PutValue (lref , restObj )。
13.15.5.5 运行时语义:IteratorDestructuringAssignmentEvaluation
语法导向操作 IteratorDestructuringAssignmentEvaluation
接受参数
iteratorRecord (一个 迭代器记录 )并返回一个
包含
unused 的正常完成记录或一个
异常完成 。它的定义如下:
AssignmentElementList
: AssignmentElisionElement
1. 返回 ? IteratorDestructuringAssignmentEvaluation 的 AssignmentElisionElement
传入参数 iteratorRecord 。
AssignmentElementList
:
AssignmentElementList
,
AssignmentElisionElement
1. 执行 ? IteratorDestructuringAssignmentEvaluation 的 AssignmentElementList
传入参数 iteratorRecord 。
2. 返回 ? IteratorDestructuringAssignmentEvaluation 的 AssignmentElisionElement
传入参数 iteratorRecord 。
AssignmentElisionElement
: AssignmentElement
1. 返回 ? IteratorDestructuringAssignmentEvaluation 的 AssignmentElement 传入参数
iteratorRecord 。
AssignmentElisionElement
:
Elision
AssignmentElement
1. 执行 ? IteratorDestructuringAssignmentEvaluation 的 Elision 传入参数
iteratorRecord 。
2. 返回 ? IteratorDestructuringAssignmentEvaluation 的 AssignmentElement 传入参数
iteratorRecord 。
Elision :
,
1. 如果 iteratorRecord .[[Done]]
是 false ,那么
a. 令 next 为 Completion (IteratorStep (iteratorRecord ))。
b. 如果 next 是一个 异常完成 ,设置
iteratorRecord .[[Done]]
为 true 。
c. ReturnIfAbrupt (next )。
d. 如果 next 是 false ,设置
iteratorRecord .[[Done]] 为 true 。
2. 返回 unused 。
Elision :
Elision
,
1. 执行 ? IteratorDestructuringAssignmentEvaluation 的 Elision 传入参数
iteratorRecord 。
2. 如果 iteratorRecord .[[Done]]
是 false ,那么
a. 令 next 为 Completion (IteratorStep (iteratorRecord ))。
b. 如果 next 是一个 异常完成 ,设置
iteratorRecord .[[Done]]
为 true 。
c. ReturnIfAbrupt (next )。
d. 如果 next 是 false ,设置
iteratorRecord .[[Done]] 为 true 。
3. 返回 unused 。
AssignmentElement
:
DestructuringAssignmentTarget
Initializer opt
1. 如果 DestructuringAssignmentTarget
既不是一个 ObjectLiteral 也不是一个 ArrayLiteral ,那么
a. 令 lref 为 ? Evaluation 的 DestructuringAssignmentTarget 。
2. 令 value 为 undefined 。
3. 如果 iteratorRecord .[[Done]]
是 false ,那么
a. 令 next 为 ? IteratorStepValue 的 iteratorRecord 。
b. 如果 next 不是 done ,那么
i. 设置 value 为 next 。
4. 如果 Initializer 存在并且
value 是 undefined ,那么
a. 如果 IsAnonymousFunctionDefinition (Initializer )
是 true 并且 IsIdentifierRef
的 DestructuringAssignmentTarget
是 true ,那么
i. 令 v 为 ? NamedEvaluation 的 Initializer 传入参数
lref .[[ReferencedName]] 。
b. 否则,
i. 令 defaultValue 为 ? Evaluation 的 Initializer 。
ii. 令 v 为 ? GetValue (defaultValue )。
5. 否则,
a. 令 v 为 value 。
6. 如果 DestructuringAssignmentTarget
是一个 ObjectLiteral 或一个 ArrayLiteral ,那么
a. 令 nestedAssignmentPattern 为一个 AssignmentPattern ,
它被 覆盖 在 DestructuringAssignmentTarget 。
b. 返回 ? DestructuringAssignmentEvaluation 的
nestedAssignmentPattern 传入参数 v 。
7. 返回 ? PutValue (lref , v )。
注
AssignmentRestElement
:
...
DestructuringAssignmentTarget
1. 如果 DestructuringAssignmentTarget
既不是一个 ObjectLiteral 也不是一个 ArrayLiteral ,那么
a. 令 lref 为 ? Evaluation 的 DestructuringAssignmentTarget 。
2. 令 A 为 ! ArrayCreate (0)。
3. 令 n 为 0。
4. 重复,直到 iteratorRecord .[[Done]]
是 false ,
a. 令 next 为 ? IteratorStepValue 的 iteratorRecord 。
b. 如果 next 不是 done ,那么
i. 执行 ! CreateDataPropertyOrThrow
的 A ,
! ToString 的 𝔽
的 n ,
next 。
ii. 设置 n 为 n + 1。
5. 如果 DestructuringAssignmentTarget
既不是一个 ObjectLiteral 也不是一个 ArrayLiteral ,那么
a. 返回 ? PutValue 的
lref ,A 。
6. 令 nestedAssignmentPattern 为一个 AssignmentPattern ,
它被 覆盖 在 DestructuringAssignmentTarget 。
7. 返回 ? DestructuringAssignmentEvaluation 的
nestedAssignmentPattern 传入参数 A 。
13.15.5.6 运行时语义:KeyedDestructuringAssignmentEvaluation
语法指向操作
KeyedDestructuringAssignmentEvaluation 接受参数 value (一个
ECMAScript 语言值
)和 propertyName (一个
属性键
),并返回一个
包含的正常完成
unused 或
异常完成
。它逐一定义在以下产生式上:
AssignmentElement
:
DestructuringAssignmentTarget
Initializer
opt
1.
如果
DestructuringAssignmentTarget
既不是
ObjectLiteral
也不是
ArrayLiteral
,那么
a.
令 lref 为 ?
Evaluation
的
DestructuringAssignmentTarget
。
2.
令 v 为 ?
GetV
的 value 和 propertyName 。
3.
如果
Initializer
存在并且 v 是 undefined ,那么
a.
如果
IsAnonymousFunctionDefinition
的
Initializer
并且
IsIdentifierRef
的
DestructuringAssignmentTarget
都为 true ,那么
i.
令 rhsValue 为 ?
NamedEvaluation
的
Initializer
传入参数 lref .[[ReferencedName]] 。
b.
否则,
i.
令 defaultValue 为 ?
Evaluation
的
Initializer
。
ii.
令 rhsValue 为 ?
GetValue
的 defaultValue 。
4.
否则,
a.
令 rhsValue 为 v 。
5.
如果
DestructuringAssignmentTarget
是一个
ObjectLiteral
或
ArrayLiteral
,那么
a.
令 assignmentPattern 为
AssignmentPattern
,它被
覆盖
在
DestructuringAssignmentTarget
。
b.
返回 ?
DestructuringAssignmentEvaluation
的 assignmentPattern 传入参数 rhsValue 。
6.
返回 ?
PutValue
的 lref ,rhsValue 。
13.16 逗号操作符 (,
)
语法
Expression
[In, Yield, Await]
:
AssignmentExpression
[?In, ?Yield, ?Await]
Expression
[?In, ?Yield, ?Await]
,
AssignmentExpression
[?In, ?Yield, ?Await]
13.16.1 运行时语义:Evaluation
Expression
:
Expression
,
AssignmentExpression
1.
令 lref 为 ?
Evaluation
的
Expression
。
2.
执行 ?
GetValue
(lref )。
3.
令 rref 为 ?
Evaluation
的
AssignmentExpression
。
4.
返回 ?
GetValue
(rref )。
注
GetValue
必须被调用,即使其值未被使用,因为它可能具有可观察的副作用。
14 ECMAScript 语言:语句和声明
语法
Statement [Yield, Await,
Return] :
BlockStatement [?Yield,
?Await, ?Return]
VariableStatement [?Yield,
?Await]
EmptyStatement
ExpressionStatement [?Yield,
?Await]
IfStatement [?Yield,
?Await, ?Return]
BreakableStatement [?Yield,
?Await, ?Return]
ContinueStatement [?Yield,
?Await]
BreakStatement [?Yield,
?Await]
[+Return]
ReturnStatement [?Yield,
?Await]
WithStatement [?Yield,
?Await, ?Return]
LabelledStatement [?Yield,
?Await, ?Return]
ThrowStatement [?Yield,
?Await]
TryStatement [?Yield,
?Await, ?Return]
DebuggerStatement
Declaration [Yield,
Await] :
HoistableDeclaration [?Yield,
?Await, ~Default]
ClassDeclaration [?Yield,
?Await, ~Default]
LexicalDeclaration [+In,
?Yield, ?Await]
HoistableDeclaration [Yield,
Await, Default] :
FunctionDeclaration [?Yield,
?Await, ?Default]
GeneratorDeclaration [?Yield,
?Await, ?Default]
AsyncFunctionDeclaration [?Yield,
?Await, ?Default]
AsyncGeneratorDeclaration [?Yield,
?Await, ?Default]
BreakableStatement [Yield,
Await, Return] :
IterationStatement [?Yield,
?Await, ?Return]
SwitchStatement [?Yield,
?Await, ?Return]
14.1 语句语义
14.1.1 运行时语义:求值
HoistableDeclaration
:
GeneratorDeclaration
AsyncFunctionDeclaration
AsyncGeneratorDeclaration
1. 返回 empty 。
HoistableDeclaration
: FunctionDeclaration
1. 返回 ? 求值 of
FunctionDeclaration 。
BreakableStatement
:
IterationStatement
SwitchStatement
1. 令 newLabelSet 为一个空的 List 。
2. 返回 ? LabelledEvaluation of this BreakableStatement with
argument newLabelSet 。
14.2 块
语法
BlockStatement [Yield,
Await, Return] :
Block [?Yield, ?Await,
?Return]
Block [Yield, Await,
Return] :
{
StatementList [?Yield,
?Await, ?Return] opt
}
StatementList [Yield,
Await, Return] :
StatementListItem [?Yield,
?Await, ?Return]
StatementList [?Yield,
?Await, ?Return]
StatementListItem [?Yield,
?Await, ?Return]
StatementListItem [Yield,
Await, Return] :
Statement [?Yield,
?Await, ?Return]
Declaration [?Yield,
?Await]
14.2.1 静态语义:早期错误
Block :
{
StatementList
}
14.2.2 运行时语义:求值
Block :
{
}
1. 返回 empty 。
Block :
{
StatementList
}
1. 令 oldEnv 为 运行中的执行上下文 的
LexicalEnvironment。
2. 令 blockEnv 为 NewDeclarativeEnvironment (oldEnv )。
3. 执行 BlockDeclarationInstantiation (StatementList ,
blockEnv )。
4. 将 运行中的执行上下文 的
LexicalEnvironment 设置为 blockEnv 。
5. 令 blockValue 为 Completion (求值 of StatementList )。
6. 将 运行中的执行上下文 的
LexicalEnvironment 设置为 oldEnv 。
7. 返回 ? blockValue 。
注 1
无论控制如何离开 Block ,LexicalEnvironment 总是恢复到其以前的状态。
StatementList
:
StatementList
StatementListItem
1. 令 sl 为 ? 求值 of StatementList 。
2. 令 s 为 Completion (求值 of StatementListItem )。
3. 返回 ? UpdateEmpty (s ,
sl )。
注 2
StatementList 的值是 StatementList
中最后一个产生值的项的值。例如,以下对 eval
函数的调用都返回值 1:
eval ("1;;;;;" )
eval ("1;{}" )
eval ("1;var a;" )
14.2.3 BlockDeclarationInstantiation ( code , env )
抽象操作 BlockDeclarationInstantiation 接受参数 code (一个 解析节点 )和
env
(一个 声明性环境记录 )并返回
unused 。code 是与块体对应的 解析节点 。env 是将在其中创建绑定的
环境记录 。
注
当 Block 或
CaseBlock
被求值时,会创建一个新的 声明性环境记录 ,并且块作用域内的每个变量、常量、函数或类声明的绑定会在
环境记录 中实例化。
当调用时,它执行以下步骤:
1. 令 declarations 为 code 的 LexicallyScopedDeclarations 。
2. 令 privateEnv 为 运行中的执行上下文 的
PrivateEnvironment。
3. 对于 declarations 的每个元素 d ,执行
a. 对于 d 的 BoundNames 的每个元素
dn ,执行
i. 如果 d 的 IsConstantDeclaration
为 true ,则
1. 执行
! env .CreateImmutableBinding(dn , true )。
ii. 否则,
1.
执行 ! env .CreateMutableBinding(dn ,
false )。注意:此步骤在 B.3.2.6
中被替换。
b. 如果 d 是 FunctionDeclaration 、
GeneratorDeclaration 、
AsyncFunctionDeclaration
或 AsyncGeneratorDeclaration ,则
i. 令 fn 为 d 的 BoundNames
的唯一元素。
ii. 令 fo 为 d 的 InstantiateFunctionObject ,参数为
env 和 privateEnv 。
iii.
执行 ! env .InitializeBinding(fn , fo )。注意:此步骤在
B.3.2.6
中被替换。
4. 返回 unused 。
14.3 声明和变量语句
14.3.1 Let 和 Const 声明
注
let
和 const
声明定义的变量作用域为 运行中的执行上下文 的
LexicalEnvironment。变量在其包含的
环境记录 被实例化时创建,但在变量的 LexicalBinding
被求值之前不能以任何方式访问。带有 Initializer 的 LexicalBinding
定义的变量在 Initializer 被求值时被赋值,而不是在变量创建时。如果
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 运行时语义:求值
LexicalDeclaration
:
LetOrConst
BindingList
;
1. 执行 ? 求值
of BindingList 。
2. 返回 empty 。
BindingList
:
BindingList
,
LexicalBinding
1. 执行 ? 求值
of BindingList 。
2. 返回 ? 求值
of LexicalBinding 。
LexicalBinding
: BindingIdentifier
1. 令 lhs 为 ! ResolveBinding (StringValue
of BindingIdentifier )。
2. 执行 ! InitializeReferencedBinding (lhs ,
undefined )。
3. 返回 empty 。
注
一个 静态语义
规则确保这种形式的 LexicalBinding 永远不会出现在
const
声明中。
LexicalBinding
:
BindingIdentifier
Initializer
1. 令 bindingId 为 StringValue
of BindingIdentifier 。
2. 令 lhs 为 ! ResolveBinding (bindingId )。
3. 如果 IsAnonymousFunctionDefinition (Initializer )
is true ,则
a. 令 value 为 ? NamedEvaluation of Initializer with argument
bindingId 。
4. 否则,
a. 令 rhs 为 ? 求值 of Initializer 。
b. 令 value 为 ? GetValue (rhs )。
5. 执行 ! InitializeReferencedBinding (lhs ,
value )。
6. 返回 empty 。
LexicalBinding
:
BindingPattern
Initializer
1. 令 rhs 为 ? 求值 of Initializer 。
2. 令 value 为 ? GetValue (rhs )。
3. 令 env 为 运行中的执行上下文 的
LexicalEnvironment。
4. 返回 ? BindingInitialization of BindingPattern with
arguments value and env 。
14.3.2 变量语句
注
一个 var
语句声明的变量作用域为 运行中的执行上下文 的
VariableEnvironment。Var 变量在其包含的
环境记录 被实例化时创建,并初始化为
undefined 。在任何 VariableEnvironment 的作用域内,一个共同的 BindingIdentifier 可能出现在多个
VariableDeclaration
中,但这些声明共同定义了一个变量。带有 Initializer 的 VariableDeclaration 定义的变量在
Initializer
被求值时被赋值,而不是在变量创建时。
语法
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 运行时语义:求值
VariableStatement
:
var
VariableDeclarationList
;
1. 执行 ? 求值
of VariableDeclarationList 。
2. 返回 empty 。
VariableDeclarationList
:
VariableDeclarationList
,
VariableDeclaration
1. 执行 ? 求值
of VariableDeclarationList 。
2. 返回 ? 求值
of VariableDeclaration 。
VariableDeclaration
: BindingIdentifier
1. 返回 empty 。
VariableDeclaration
:
BindingIdentifier
Initializer
1. 令 bindingId 为 StringValue
of BindingIdentifier 。
2. 令 lhs 为 ? ResolveBinding (bindingId )。
3. 如果 IsAnonymousFunctionDefinition (Initializer )
is true ,则
a. 令 value 为 ? NamedEvaluation of Initializer with argument
bindingId 。
4. 否则,
a. 令 rhs 为 ? 求值 of Initializer 。
b. 令 value 为 ? GetValue (rhs )。
5. 执行 ? PutValue (lhs , value )。
6. 返回 empty 。
注
如果一个 VariableDeclaration 嵌套在一个
with 语句中,并且 BindingIdentifier 在 VariableDeclaration 中与 with
语句的绑定对象的 属性名 相同,那么步骤 5 将把
value 赋值给该属性,而不是赋值给 VariableEnvironment 绑定。
VariableDeclaration
:
BindingPattern
Initializer
1. 令 rhs 为 ? 求值 of Initializer 。
2. 令 rval 为 ? GetValue (rhs )。
3. 返回 ? BindingInitialization of BindingPattern with
arguments rval and undefined 。
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 运行时语义:属性绑定初始化
属性绑定初始化是一个 语法导向操作 ,它接受参数
value (一个
ECMAScript 语言值 )和
environment (一个 环境记录 或
undefined ),并返回一个 正常完成 包含一个
列表 的 属性键 或一个 突然完成 。它收集所有绑定属性名的列表。它在以下产生式上分段定义:
BindingPropertyList
:
BindingPropertyList
,
BindingProperty
1. 令 boundNames 为 ? 属性绑定初始化 of BindingPropertyList
使用参数 value 和 environment 。
2. 令 nextNames 为 ? 属性绑定初始化 of BindingProperty 使用参数
value 和 environment 。
3. 返回 boundNames 和 nextNames 的 列表连接 。
BindingProperty
: SingleNameBinding
1. 令 name 为 SingleNameBinding 的 BoundNames 的唯一元素。
2. 执行 ? 键绑定初始化 of SingleNameBinding 使用参数
value 、environment 和 name 。
3. 返回 « name »。
BindingProperty
:
PropertyName
:
BindingElement
1. 令 P 为 ? 求值 of PropertyName 。
2. 执行 ? 键绑定初始化 of BindingElement 使用参数
value 、environment 和 P 。
3. 返回 « P »。
14.3.3.2 运行时语义:剩余绑定初始化
剩余绑定初始化是一个 语法导向操作 ,它接受参数
value (一个 ECMAScript
语言值 )、environment (一个 环境记录 或
undefined )和 excludedNames (一个 列表 的 属性键 ),并返回一个 正常完成 包含
unused 或一个 突然完成 。它在以下产生式上分段定义:
BindingRestProperty
:
...
BindingIdentifier
1. 令 lhs 为 ? ResolveBinding (StringValue
of BindingIdentifier ,
environment )。
2. 令 restObj 为 OrdinaryObjectCreate (%Object.prototype% )。
3. 执行 ? CopyDataProperties (restObj , value ,
excludedNames )。
4. 如果 environment 是 undefined ,
返回 ? PutValue (lhs , restObj )。
5. 返回 ? InitializeReferencedBinding (lhs ,
restObj )。
14.3.3.3 运行时语义:键绑定初始化
键绑定初始化是一个 语法导向操作 ,它接受参数
value (一个 ECMAScript
语言值 )、environment (一个 环境记录 或
undefined )和 propertyName (一个 属性键 ),并返回一个 正常完成 包含
unused 或一个 突然完成 。它定义在以下产生式上分段:
注
当 undefined 作为 environment 传递时,表示应该使用 PutValue
操作来分配初始化值。这种情况发生在 非严格函数
的形式参数列表中。在这种情况下,形式参数绑定是预初始化的,以处理多个参数具有相同名称的可能性。
它在以下产生式上分段定义:
BindingElement
:
BindingPattern
Initializer opt
1. 令 v 为 ? GetV (value , propertyName )。
2. 如果 Initializer 存在且 v 是
undefined ,则
a. 令 defaultValue 为 ? 求值 of Initializer 。
b. 设置 v 为 ? GetValue (defaultValue )。
3. 返回 ? 绑定初始化 of BindingPattern 使用参数 v
和 environment 。
SingleNameBinding
:
BindingIdentifier
Initializer opt
1. 令 bindingId 为 StringValue
of BindingIdentifier 。
2. 令 lhs 为 ? ResolveBinding (bindingId ,
environment )。
3. 令 v 为 ? GetV (value , propertyName )。
4. 如果 Initializer 存在且 v 是
undefined ,则
a. 如果 IsAnonymousFunctionDefinition (Initializer )
is
true ,则
i. 设置 v 为 ? NamedEvaluation of Initializer with
argument bindingId 。
b. 否则,
i. 令 defaultValue 为 ? 求值 of Initializer 。
ii. 设置 v 为 ? GetValue (defaultValue )。
5. 如果 environment 是 undefined ,
返回 ? PutValue (lhs , v )。
6. 返回 ? InitializeReferencedBinding (lhs ,
v )。
14.4 空语句
语法
EmptyStatement
:
;
14.4.1 运行时语义:求值
EmptyStatement
: ;
1. 返回 empty 。
14.5 表达式语句
语法
ExpressionStatement [Yield,
Await] :
[lookahead ∉ { { , function , async
[no LineTerminator
here]
function , class , let
[ }]
Expression [+In, ?Yield,
?Await]
;
注
14.5.1 运行时语义:求值
ExpressionStatement
:
Expression
;
1. 令 exprRef 为 ? 求值 of Expression 。
2. 返回 ? GetValue (exprRef )。
14.6 if
语句
语法
IfStatement [Yield,
Await, Return] :
if
(
Expression [+In, ?Yield,
?Await]
)
Statement [?Yield,
?Await, ?Return]
else
Statement [?Yield,
?Await, ?Return]
if
(
Expression [+In, ?Yield,
?Await]
)
Statement [?Yield,
?Await, ?Return]
[lookahead ≠ else ]
注
前瞻限制 [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 运行时语义:求值
IfStatement
:
if
(
Expression
)
Statement
else
Statement
1. 设 exprRef 为 ? 求值 of Expression .
2. 设 exprValue 为 ToBoolean (?
GetValue (exprRef )).
3. 如果 exprValue 是 true ,则
a. 设 stmtCompletion 为 Completion (求值 of the first Statement ).
4. 否则
a. 设 stmtCompletion 为 Completion (求值 of the second Statement ).
5. 返回 ? UpdateEmpty (stmtCompletion ,
undefined ).
IfStatement
:
if
(
Expression
)
Statement
1. 设 exprRef 为 ? 求值 of Expression .
2. 设 exprValue 为 ToBoolean (?
GetValue (exprRef )).
3. 如果 exprValue 是 false ,则
a. 返回 undefined .
4. 否则
a. 设 stmtCompletion 为 Completion (求值 of Statement ).
b. 返回 ? 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 (一个 Completion
Record )和 labelSet (一个 List of
Strings)并返回一个 Boolean。它在调用时执行以下步骤:
1. 如果 completion 是一个 normal
completion ,返回 true 。
2. 如果 completion 不是一个 continue
completion ,返回 false 。
3. 如果 completion .[[Target]]
是
empty ,返回 true 。
4. 如果 labelSet 包含 completion .[[Target]] ,返回 true 。
5. 返回 false 。
注
14.7.1.2 运行时语义:LoopEvaluation
语法导向操作 LoopEvaluation 接受参数 labelSet (一个 List of
Strings)并返回一个 normal
completion
containing 一个 ECMAScript language
value 或一个 abrupt
completion 。它在以下产生式上定义:
IterationStatement
: DoWhileStatement
1. 返回 ? DoWhileLoopEvaluation of DoWhileStatement with
argument labelSet .
IterationStatement
: WhileStatement
1. 返回 ? WhileLoopEvaluation of WhileStatement with argument
labelSet .
IterationStatement
: ForStatement
1. 返回 ? ForLoopEvaluation of ForStatement with argument
labelSet .
IterationStatement
: ForInOfStatement
1. 返回 ? ForInOfLoopEvaluation of ForInOfStatement with
argument labelSet .
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 (一个 List of
Strings)并返回一个 normal
completion
containing 一个 ECMAScript language
value 或一个 abrupt
completion 。它在以下产生式上定义:
DoWhileStatement
:
do
Statement
while
(
Expression
)
;
1. 设 V 为 undefined 。
2. 重复,
a. 设 stmtResult 为 Completion (求值 of Statement )。
b. 如果 LoopContinues (stmtResult ,
labelSet ) 是 false ,返回 ? UpdateEmpty (stmtResult ,
V )。
c. 如果 stmtResult .[[Value]]
不是 empty ,设 V 为 stmtResult .[[Value]] 。
d. 设 exprRef 为 ? 求值 of Expression 。
e. 设 exprValue 为 ? GetValue (exprRef )。
f. 如果 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 (一个 List of
Strings)并返回一个 normal
completion
containing 一个 ECMAScript language
value 或一个 abrupt
completion 。它在以下产生式上定义:
WhileStatement
:
while
(
Expression
)
Statement
1. 设 V 为 undefined 。
2. 重复,
a. 设 exprRef 为 ? 求值 of Expression 。
b. 设 exprValue 为 ? GetValue (exprRef )。
c. 如果 ToBoolean (exprValue )
是 false ,返回 V 。
d. 设 stmtResult 为 Completion (求值 of Statement )。
e. 如果 LoopContinues (stmtResult ,
labelSet ) 是 false ,返回 ? UpdateEmpty (stmtResult ,
V )。
f. 如果 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 (一个 List of
Strings)并返回一个 normal
completion
containing 一个 ECMAScript language
value 或一个 abrupt
completion 。它在以下产生式上定义:
ForStatement
:
for
(
Expression opt
;
Expression opt
;
Expression opt
)
Statement
1. 如果第一个 Expression 存在,则
a. 设 exprRef 为 ? 求值 of the first Expression 。
b. 执行 ? GetValue (exprRef )。
2. 如果第二个 Expression 存在,设
test 为第二个 Expression ;否则,设
test 为 empty 。
3. 如果第三个 Expression 存在,设
increment 为第三个 Expression ;否则,设
increment 为 empty 。
4. 返回 ? ForBodyEvaluation (test , increment ,
Statement ,
« », labelSet )。
ForStatement
:
for
(
var
VariableDeclarationList
;
Expression opt
;
Expression opt
)
Statement
1. 执行 ? 求值
of VariableDeclarationList 。
2. 如果第一个 Expression 存在,设
test 为第一个 Expression ;否则,设
test 为 empty 。
3. 如果第二个 Expression 存在,设
increment 为第二个 Expression ;否则,设
increment 为 empty 。
4. 返回 ? ForBodyEvaluation (test , increment ,
Statement ,
« », labelSet )。
ForStatement
:
for
(
LexicalDeclaration
Expression opt
;
Expression opt
)
Statement
1. 设 oldEnv 为 运行执行上下文 的词法环境。
2. 设 loopEnv 为 NewDeclarativeEnvironment (oldEnv )。
3. 设 isConst 为 IsConstantDeclaration
of LexicalDeclaration 。
4. 设 boundNames 为 BoundNames of
LexicalDeclaration 。
5. 对于 boundNames 的每个元素 dn ,执行
a. 如果 isConst 是 true ,则
i. 执行
! loopEnv .CreateImmutableBinding(dn , true )。
b. 否则,
i. 执行
! loopEnv .CreateMutableBinding(dn , false )。
6. 将 运行执行上下文 的词法环境设置为
loopEnv 。
7. 设 forDcl 为 Completion (求值 of LexicalDeclaration )。
8. 如果 forDcl 是一个 abrupt
completion ,则
a. 将 运行执行上下文 的词法环境设置为
oldEnv 。
b. 返回 ? forDcl 。
9. 如果 isConst 是 false ,设
perIterationLets 为 boundNames ;否则设 perIterationLets 为
一个新的空 List 。
10. 如果第一个 Expression 存在,设
test 为第一个 Expression ;否则,设
test 为 empty 。
11. 如果第二个 Expression 存在,设
increment 为第二个 Expression ;否则,设
increment 为 empty 。
12. 设 bodyResult 为 Completion (ForBodyEvaluation (test , increment ,
Statement ,
perIterationLets , labelSet ))。
13. 将 运行执行上下文 的词法环境设置为
oldEnv 。
14. 返回 ? bodyResult 。
14.7.4.3 ForBodyEvaluation ( test , increment ,
stmt , perIterationBindings , labelSet )
抽象操作 ForBodyEvaluation 接受参数 test (一个 Expression
Parse Node 或
empty ),increment (一个 Expression Parse Node 或
empty ),stmt (一个 Statement Parse Node ),
perIterationBindings (一个 List of
Strings),和 labelSet (一个 List of
Strings)并返回一个 normal
completion
containing 一个 ECMAScript language
value 或一个 abrupt
completion 。它在调用时执行以下步骤:
1. 设 V 为 undefined 。
2. 执行 ? CreatePerIterationEnvironment (perIterationBindings )。
3. 重复,
a. 如果 test 不是 empty ,则
i. 设 testRef 为 ? 求值 of test 。
ii. 设 testValue 为 ? GetValue (testRef )。
iii. 如果 ToBoolean (testValue )
是 false ,返回 V 。
b. 设 result 为 Completion (求值 of stmt )。
c. 如果 LoopContinues (result ,
labelSet ) 是 false ,返回 ? UpdateEmpty (result ,
V )。
d. 如果 result .[[Value]]
不是 empty ,设 V 为 result .[[Value]] 。
e. 执行 ? CreatePerIterationEnvironment (perIterationBindings )。
f. 如果 increment 不是
empty ,则
i. 设 incRef 为 ? 求值 of increment 。
ii. 执行 ? GetValue (incRef )。
14.7.4.4 CreatePerIterationEnvironment ( perIterationBindings
)
抽象操作 CreatePerIterationEnvironment 接受参数 perIterationBindings
(一个
List of
Strings)并返回一个 normal
completion
containing unused 或一个 throw
completion 。它在调用时执行以下步骤:
1. 如果 perIterationBindings 有任何元素,则
a. 设 lastIterationEnv 为 运行执行上下文 的词法环境。
b. 设 outer 为 lastIterationEnv .[[OuterEnv]] 。
c. 断言 :outer 不是
null 。
d. 设 thisIterationEnv 为 NewDeclarativeEnvironment (outer )。
e. 对于 perIterationBindings 的每个元素 bn ,执行
i. 执行
! thisIterationEnv .CreateMutableBinding(bn ,
false )。
ii. 设 lastValue 为
? lastIterationEnv .GetBindingValue(bn ,
true )。
iii. 执行
! thisIterationEnv .InitializeBinding(bn , lastValue )。
f. 将 运行执行上下文 的词法环境设置为
thisIterationEnv 。
2. 返回 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
如果 LeftHandSideExpression
是 ObjectLiteral 或 ArrayLiteral ,则以下早期错误规则适用:
如果 LeftHandSideExpression
既不是 ObjectLiteral 也不是 ArrayLiteral ,则以下早期错误规则适用:
ForInOfStatement
:
for
(
ForDeclaration
in
Expression
)
Statement
for
(
ForDeclaration
of
AssignmentExpression
)
Statement
for
await
(
ForDeclaration
of
AssignmentExpression
)
Statement
14.7.5.2 静态语义:IsDestructuring
语法导向操作 IsDestructuring 不接受参数并返回一个布尔值。它在以下产生式上定义:
MemberExpression
: PrimaryExpression
1. 如果 PrimaryExpression 是
ObjectLiteral 或 ArrayLiteral ,
返回 true 。
2. 返回 false 。
MemberExpression
:
MemberExpression
[
Expression
]
MemberExpression
.
IdentifierName
MemberExpression
TemplateLiteral
SuperProperty
MetaProperty
new
MemberExpression
Arguments
MemberExpression
.
PrivateIdentifier
NewExpression
:
new
NewExpression
LeftHandSideExpression
:
CallExpression
OptionalExpression
1. 返回 false 。
ForDeclaration
:
LetOrConst
ForBinding
1. 返回 IsDestructuring
of ForBinding 。
ForBinding
: BindingIdentifier
1. 返回 false 。
ForBinding
: BindingPattern
1. 返回 true 。
注
14.7.5.3 运行时语义:ForDeclarationBindingInitialization
语法导向操作 ForDeclarationBindingInitialization 接受参数 value (一个
ECMAScript 语言值 )和
environment (一个 环境记录 或
undefined )并返回一个 正常完成包含
unused 或一个 异常完成 。
注
undefined 传递给 environment 表示应使用 PutValue
操作来分配初始化值。这适用于
var
语句和某些 非严格函数 的形式参数列表(参见
10.2.11 )。
在这些情况下,词法绑定被提升并在评估其初始化器之前预初始化。
它在以下产生式上定义:
ForDeclaration
:
LetOrConst
ForBinding
1. 返回 ? BindingInitialization of ForBinding with arguments
value and environment 。
14.7.5.4 运行时语义:ForDeclarationBindingInstantiation
语法导向操作 ForDeclarationBindingInstantiation 接受参数 environment (一个
声明性环境记录 )并返回
unused 。它在以下产生式上定义:
ForDeclaration
:
LetOrConst
ForBinding
1. 对于 BoundNames of
ForBinding
的每个元素 name ,执行
a. 如果 IsConstantDeclaration
of LetOrConst 是
true ,则
i. 执行
! environment .CreateImmutableBinding(name ,
true )。
b. 否则,
i. 执行
! environment .CreateMutableBinding(name ,
false )。
2. 返回 unused 。
14.7.5.5 运行时语义:ForInOfLoopEvaluation
语法导向操作 ForInOfLoopEvaluation 接受参数 labelSet (一个 List of
Strings)并返回一个 正常完成包含
一个 ECMAScript 语言值 或一个
异常完成 。它在以下产生式上定义:
ForInOfStatement
:
for
(
LeftHandSideExpression
in
Expression
)
Statement
1. 设 keyResult 为 ? ForIn/OfHeadEvaluation (« », Expression ,
enumerate )。
2. 返回 ? ForIn/OfBodyEvaluation (LeftHandSideExpression ,
Statement ,
keyResult , enumerate , assignment ,
labelSet )。
ForInOfStatement
:
for
(
var
ForBinding
in
Expression
)
Statement
1. 设 keyResult 为 ? ForIn/OfHeadEvaluation (« », Expression ,
enumerate )。
2. 返回 ? ForIn/OfBodyEvaluation (ForBinding , Statement ,
keyResult , enumerate , var-binding ,
labelSet )。
ForInOfStatement
:
for
(
ForDeclaration
in
Expression
)
Statement
1. 设 keyResult 为 ? ForIn/OfHeadEvaluation (BoundNames of
ForDeclaration , Expression ,
enumerate )。
2. 返回 ? ForIn/OfBodyEvaluation (ForDeclaration , Statement ,
keyResult , enumerate , lexical-binding ,
labelSet )。
ForInOfStatement
:
for
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
1. 设 keyResult 为 ? ForIn/OfHeadEvaluation (« », AssignmentExpression ,
iterate )。
2. 返回 ? ForIn/OfBodyEvaluation (LeftHandSideExpression ,
Statement ,
keyResult , iterate , assignment ,
labelSet )。
ForInOfStatement
:
for
(
var
ForBinding
of
AssignmentExpression
)
Statement
1. 设 keyResult 为 ? ForIn/OfHeadEvaluation (« », AssignmentExpression ,
iterate )。
2. 返回 ? ForIn/OfBodyEvaluation (ForBinding , Statement ,
keyResult , iterate , var-binding ,
labelSet )。
ForInOfStatement
:
for
(
ForDeclaration
of
AssignmentExpression
)
Statement
1. 设 keyResult 为 ? ForIn/OfHeadEvaluation (BoundNames of
ForDeclaration , AssignmentExpression ,
iterate )。
2. 返回 ? ForIn/OfBodyEvaluation (ForDeclaration , Statement ,
keyResult , iterate , lexical-binding ,
labelSet )。
ForInOfStatement
:
for
await
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
1. 设 keyResult 为 ? ForIn/OfHeadEvaluation (« », AssignmentExpression ,
async-iterate )。
2. 返回 ? ForIn/OfBodyEvaluation (LeftHandSideExpression ,
Statement ,
keyResult , iterate , assignment ,
labelSet , async )。
ForInOfStatement
:
for
await
(
var
ForBinding
of
AssignmentExpression
)
Statement
1. 设 keyResult 为 ? ForIn/OfHeadEvaluation (« », AssignmentExpression ,
async-iterate )。
2. 返回 ? ForIn/OfBodyEvaluation (ForBinding , Statement ,
keyResult , iterate , var-binding ,
labelSet , async )。
ForInOfStatement
:
for
await
(
ForDeclaration
of
AssignmentExpression
)
Statement
1. 设 keyResult 为 ? ForIn/OfHeadEvaluation (BoundNames of
ForDeclaration , AssignmentExpression ,
async-iterate )。
2. 返回 ? ForIn/OfBodyEvaluation (ForDeclaration , Statement ,
keyResult , iterate , lexical-binding ,
labelSet , async )。
注
14.7.5.6 ForIn/OfHeadEvaluation ( uninitializedBoundNames ,
expr , iterationKind )
抽象操作 ForIn/OfHeadEvaluation 接受参数 uninitializedBoundNames (一个
字符串列表 ),expr (一个
表达式
解析节点 或一个
赋值表达式
解析节点 ),以及
iterationKind (enumerate ,iterate ,或
async-iterate ),并返回一个
正常完成记录 包含一个
迭代器记录 或一个
异常完成记录 。它在调用时执行以下步骤:
1. 令 oldEnv 为
运行执行上下文 的词法环境。
2. 如果 uninitializedBoundNames 不为空,则
a. 断言 :
uninitializedBoundNames 没有重复条目。
b. 令 newEnv 为
NewDeclarativeEnvironment (oldEnv )。
c. 对于 uninitializedBoundNames 中的每个字符串
name ,执行
i. 执行
! newEnv .CreateMutableBinding(name , false )。
d. 将
运行执行上下文 的词法环境设置为
newEnv 。
3. 令 exprRef 为
Completion (Evaluation of expr )。
4. 将
运行执行上下文 的词法环境设置为
oldEnv 。
5. 令 exprValue 为 ? GetValue (? exprRef )。
6. 如果 iterationKind 是
enumerate ,则
a. 如果 exprValue 是
undefined 或 null ,则
i. 返回
完成记录
{ [[Type]] :
break ,
[[Value]] : empty , [[Target]] : empty }。
b. 令 obj 为 ! ToObject (exprValue )。
c. 令 iterator 为
EnumerateObjectProperties (obj )。
d. 令 nextMethod 为 ! GetV (iterator ,
"next" )。
e. 返回
迭代器记录 { [[Iterator]] : iterator , [[NextMethod]] :
nextMethod , [[Done]] :
false }。
7. 否则
a. 断言 :iterationKind 是
iterate 或 async-iterate 。
b. 如果 iterationKind 是
async-iterate ,令 iteratorKind 为
async 。
c. 否则,令 iteratorKind 为
sync 。
d. 返回 ? GetIterator (exprValue ,
iteratorKind )。
14.7.5.7 ForIn/OfBodyEvaluation ( lhs , stmt ,
iteratorRecord , iterationKind , lhsKind , labelSet [ ,
iteratorKind ] )
抽象操作 ForIn/OfBodyEvaluation 接受参数 lhs (一个
解析节点 ),stmt
(一个 语句
解析节点 ),
iteratorRecord (一个 迭代器记录 ),
iterationKind (enumerate 或 iterate ),
lhsKind (assignment ,var-binding ,或
lexical-binding ),以及 labelSet (一个
字符串列表 ),
以及可选参数 iteratorKind (sync 或
async ),并返回一个
正常完成记录
包含一个 ECMAScript 语言值
或一个 异常完成记录 。
它在调用时执行以下步骤:
1. 如果 iteratorKind 不存在,设置
iteratorKind 为 sync 。
2. 令 oldEnv 为
运行执行上下文 的词法环境。
3. 令 V 为 undefined 。
4. 令 destructuring 为
IsDestructuring
的 lhs 。
5. 如果 destructuring 为 true 且
lhsKind 为 assignment ,则
a. 断言 :lhs 是一个
LeftHandSideExpression 。
b. 令 assignmentPattern 为
AssignmentPattern
的 覆盖 的
lhs 。
6. 重复,
a. 令 nextResult 为 ? Call (iteratorRecord .[[NextMethod]] , iteratorRecord .[[Iterator]] )。
b. 如果 iteratorKind 是
async ,
设置 nextResult 为 ? Await (nextResult )。
c. 如果 nextResult 不是一个
Object ,抛出一个 TypeError 异常。
d. 令 done 为 ? IteratorComplete (nextResult )。
e. 如果 done 是 true ,返回
V 。
f. 令 nextValue 为 ? IteratorValue (nextResult )。
g. 如果 lhsKind 是
assignment 或 var-binding ,则
i. 如果 destructuring 是
true ,
则
1. 如果 lhsKind 是
assignment ,则
a. 令 status 为 Completion (DestructuringAssignmentEvaluation of
assignmentPattern with argument nextValue )。
2. 否则,
a. 断言 :
lhsKind 是 var-binding 。
b. 断言 :lhs
是一个 ForBinding 。
c. 令 status 为 Completion (BindingInitialization of lhs
使用
参数 nextValue 和 undefined )。
ii. 否则,
1. 令 lhsRef 为 Completion (Evaluation of lhs )。(可能会被
多次评估。)
2. 如果 lhsRef 是一个 异常
完成 ,则
a. 令 status 为 lhsRef 。
3. 否则,
a. 令 status 为 Completion (PutValue (lhsRef .[[Value]] , nextValue ))。
h. 否则,
i. 断言 :lhsKind 是
lexical-binding 。
ii. 断言 :lhs 是一个
ForDeclaration 。
iii. 令 iterationEnv 为 NewDeclarativeEnvironment (oldEnv )。
iv. 执行 ForDeclarationBindingInstantiation
的 lhs 使用参数 iterationEnv 。
v. 设置 运行
执行上下文 的词法环境为 iterationEnv 。
vi. 如果 destructuring 是
true ,
则
1. 令 status 为 Completion (ForDeclarationBindingInitialization of
lhs 使用参数 nextValue 和 iterationEnv )。
vii. 否则,
1. 断言 :lhs
绑定一个单一的名称。
2. 令 lhsName 为
BoundNames
的 lhs 的唯一元素。
3. 令 lhsRef 为 ! ResolveBinding (lhsName )。
4. 令 status 为 Completion (InitializeReferencedBinding (lhsRef ,
nextValue ))。
i. 如果 status 是一个 异常
完成 ,则
i. 设置 运行
执行上下文 的词法环境为 oldEnv 。
ii. 如果 iteratorKind 是
async ,返回 ? AsyncIteratorClose (iteratorRecord ,
status )。
iii. 如果 iterationKind 是
enumerate ,则
1. 返回 ? status 。
iv. 否则,
1. 断言 :
iterationKind 是 iterate 。
2. 返回 ? IteratorClose (iteratorRecord ,
status )。
j. 令 result 为 Completion (Evaluation of stmt )。
k. 设置 运行
执行上下文 的词法环境为 oldEnv 。
l. 如果 LoopContinues (result ,
labelSet ) 是 false ,则
i. 如果 iterationKind 是
enumerate ,则
1. 返回 ? UpdateEmpty (result ,
V )。
ii. 否则,
1. 断言 :
iterationKind 是 iterate 。
2. 设置 status 为 Completion (UpdateEmpty (result ,
V ))。
3. 如果 iteratorKind 是
async ,返回 ? AsyncIteratorClose (iteratorRecord ,
status )。
4. 返回 ? IteratorClose (iteratorRecord ,
status )。
m. 如果 result .[[Value]]
不是 empty ,设置 V 为 result .[[Value]] 。
14.7.5.8 运行时语义:评估
BindingIdentifier
:
Identifier
yield
await
1. 令 bindingId 为 StringValue
的 BindingIdentifier 。
2. 返回 ? ResolveBinding (bindingId )。
14.7.5.9 EnumerateObjectProperties ( O )
抽象操作 EnumerateObjectProperties 接受参数 O (一个对象)并返回一个迭代器。它在调用时执行以下步骤:
1. 返回一个迭代器对象(27.1.1.2 ),其
next
方法遍历 O 的所有可枚举的字符串键属性。迭代器对象对 ECMAScript
代码永远不可直接访问。遍历属性的机制和顺序未指定,但必须符合以下规则。
迭代器的 throw
和 return
方法是 null ,并且永远不会被调用。迭代器的
next
方法处理对象属性以确定属性键是否应作为迭代器值返回。返回的属性键不包括 Symbols。目标对象的属性可能在枚举期间被删除。在迭代器的 next
方法处理之前删除的属性将被忽略。如果在枚举期间向目标对象添加新属性,则不能保证新添加的属性会在活动枚举中被处理。一个属性名在任何枚举中最多由迭代器的 next
方法返回一次。
枚举目标对象的属性包括枚举其原型及其原型的原型等的属性,递归地;但如果原型的属性与迭代器的 next
方法已经处理的属性同名,则不处理原型的属性。原型对象的可枚举属性名必须通过调用
EnumerateObjectProperties 并将原型对象作为参数来获取。EnumerateObjectProperties 必须通过调用目标对象的 [[OwnPropertyKeys]] 内部方法来获取目标对象的自有属性键。目标对象的属性属性必须通过调用其 [[GetOwnProperty]] 内部方法来获取。
此外,如果 O 或其原型链中的任何对象不是 Proxy
奇特对象 、TypedArray 、模块命名空间奇特对象 ,或实现提供的
奇特对象 ,则迭代器必须表现得像由 CreateForInIterator (O )
给出的迭代器,直到以下情况之一发生:
O 或其原型链中的对象的 [[Prototype]] 内部槽的值发生变化,
O 或其原型链中的对象的属性被删除,
O 的原型链中的对象的属性被添加,或
O 或其原型链中的对象的属性的 [[Enumerable]] 属性发生变化。
注1
ECMAScript 实现不需要直接实现 14.7.5.10.2.1
中的算法。它们可以选择任何实现,只要其行为不会偏离该算法,除非违反了前一段中的约束。
以下是一个符合这些规则的 ECMAScript 生成器函数的非正式定义:
function * EnumerateObjectProperties (obj) {
const visited = new Set ();
for (const key of Reflect .ownKeys (obj)) {
if (typeof key === "symbol" ) continue ;
const desc = Reflect .getOwnPropertyDescriptor (obj, key);
if (desc) {
visited.add (key);
if (desc.enumerable ) yield key;
}
}
const proto = Reflect .getPrototypeOf (obj);
if (proto === null ) return ;
for (const protoKey of EnumerateObjectProperties (proto)) {
if (!visited.has (protoKey)) yield protoKey;
}
}
注2
实现不需要匹配
CreateForInIterator 的
奇特对象
列表是基于历史实现在这些情况下存在差异,并且在所有其他情况下达成一致。
14.7.5.10 For-In 迭代器对象
For-In 迭代器是表示特定对象上的特定迭代的对象。For-In 迭代器对象永远不会直接对 ECMAScript 代码可访问;它们仅存在于阐明 EnumerateObjectProperties
的行为。
14.7.5.10.1 CreateForInIterator ( object )
抽象操作 CreateForInIterator 接受参数 object (一个对象)并返回一个 For-In 迭代器。它用于创建一个 For-In 迭代器对象,该对象按特定顺序迭代
object 的自身和继承的可枚举字符串属性。调用时执行以下步骤:
1. 令 iterator 为 OrdinaryObjectCreate (%ForInIteratorPrototype% ,
« [[Object]] , [[ObjectWasVisited]] , [[VisitedKeys]] , [[RemainingKeys]] »)。
2. 将 iterator .[[Object]] 设置为
object 。
3. 将 iterator .[[ObjectWasVisited]] 设置为 false 。
4. 将 iterator .[[VisitedKeys]]
设置为一个新的空 列表 。
5. 将 iterator .[[RemainingKeys]] 设置为一个新的空 列表 。
6. 返回 iterator 。
14.7.5.10.2 %ForInIteratorPrototype% 对象
%ForInIteratorPrototype% 对象:
14.7.5.10.2.1 %ForInIteratorPrototype%.next ( )
1. 令 O 为 this 值。
2. 断言 :O 是一个 对象 。
3. 断言 :O 具有 For-In 迭代器实例的所有内部槽
(14.7.5.10.3 )。
4. 令 object 为 O .[[Object]] 。
5. 重复,
a. 如果 O .[[ObjectWasVisited]] 为 false ,则
i. 令 keys 为 ? object .[[OwnPropertyKeys]] () 。
ii. 对 keys 的每个元素 key ,执行
1. 如果 key 是一个 字符串 ,则
a. 将 key 追加到 O .[[RemainingKeys]] 。
iii. 将 O .[[ObjectWasVisited]] 设置为 true 。
b. 重复,直到 O .[[RemainingKeys]] 为空,
i. 令 r 为 O .[[RemainingKeys]] 的第一个元素。
ii. 从 O .[[RemainingKeys]] 中移除第一个元素。
iii. 如果 O .[[VisitedKeys]] 中不存在一个元素 v 使得 SameValue (r ,
v ) 为 true ,则
1. 令 desc 为 ? object .[[GetOwnProperty]] (r )。
2. 如果 desc 不为
undefined ,则
a. 将 r 追加到 O .[[VisitedKeys]] 。
b. 如果 desc .[[Enumerable]] 为 true ,返回 CreateIterResultObject (r ,
false )。
c. 将 object 设置为 ? object .[[GetPrototypeOf]] () 。
d. 将 O .[[Object]] 设置为
object 。
e. 将 O .[[ObjectWasVisited]] 设置为 false 。
f. 如果 object 为 null ,返回
CreateIterResultObject (undefined ,
true )。
14.7.5.10.3 For-In 迭代器实例的属性
For-In 迭代器实例是 普通对象 ,它们从 %ForInIteratorPrototype%
内部对象继承属性。For-In 迭代器实例初始创建时具有 表 39 中列出的内部槽。
表 39: 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 运行时语义:求值
ContinueStatement
:
continue
;
1. 返回
完成记录
{ [[Type]] : continue , [[Value]] : empty , [[Target]] :
empty }.
ContinueStatement
:
continue
LabelIdentifier
;
1. 令 label 为
StringValue
的
LabelIdentifier
。
2. 返回
完成记录
{ [[Type]] : continue , [[Value]] : empty , [[Target]] :
label }.
14.9 break
语句
语法
BreakStatement
[Yield, Await]
:
break
;
break
[no
LineTerminator
here]
LabelIdentifier
[?Yield, ?Await]
;
14.9.1 静态语义:早期错误
BreakStatement
:
break
;
14.9.2 运行时语义:求值
BreakStatement
:
break
;
1. 返回
完成记录
{ [[Type]] : break , [[Value]] : empty , [[Target]] :
empty }.
BreakStatement
:
break
LabelIdentifier
;
1. 令 label 为
StringValue
的
LabelIdentifier
。
2. 返回
完成记录
{ [[Type]] : break , [[Value]] : empty , [[Target]] :
label }.
14.10 return
语句
语法
ReturnStatement
[Yield, Await]
:
return
;
return
[no
LineTerminator
here]
Expression
[+In, ?Yield, ?Await]
;
Note
return
语句会导致函数停止执行,并在大多数情况下返回一个值给调用者。如果省略了
Expression
,返回值为 undefined 。否则,返回值是
Expression
的值。根据周围的上下文,return
语句可能实际上不会返回值给调用者。例如,在
try
块中,return
语句的
Completion Record
可能在执行 finally
块时被另一个
Completion Record
替换。
14.10.1 运行时语义:求值
ReturnStatement
:
return
;
1. 返回
Completion Record
{ [[Type]] : return , [[Value]] :
undefined , [[Target]] : empty }.
ReturnStatement
:
return
Expression
;
1. 令 exprRef 为 ?
Evaluation
的
Expression
。
2. 令 exprValue 为 ?
GetValue
(exprRef )。
3. 如果
GetGeneratorKind
() 是 async ,设置 exprValue 为 ?
Await
(exprValue )。
4. 返回
Completion Record
{ [[Type]] : return , [[Value]] :
exprValue , [[Target]] : empty }.
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 运行时语义:求值
WithStatement
:
with
(
Expression
)
Statement
1. 令 val 为 ?
Evaluation
的
Expression
。
2. 令 obj 为 ?
ToObject
(?
GetValue
(val ))。
3. 令 oldEnv 为当前执行上下文的
词法环境
。
4. 令 newEnv 为
NewObjectEnvironment
(obj , true , oldEnv )。
5. 将当前执行上下文的
词法环境
设置为 newEnv 。
6. 令 C 为
Completion
(
Evaluation
的
Statement
)。
7. 将当前执行上下文的
词法环境
设置回 oldEnv 。
8. 返回 ?
UpdateEmpty
(C , undefined )。
注
无论以何种方式退出嵌入的
Statement
,无论是正常还是以某种形式的
中止完成
或异常,词法环境总是恢复到原来的状态。
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, ?Return]
opt
DefaultClause
[Yield, Await, Return]
:
default
:
StatementList
[?Yield, ?Return]
opt
14.12.1 静态语义:早期错误
SwitchStatement
:
switch
(
Expression
)
CaseBlock
14.12.2 运行时语义:CaseBlockEvaluation
语法定向操作
CaseBlockEvaluation 接受参数 input (一个
ECMAScript 语言值
),并返回
正常完成包含的
ECMAScript 语言值
或
中止完成
。它在以下产生式上分段定义:
CaseBlock
:
{
}
1. 返回 undefined 。
CaseBlock
:
{
CaseClauses
}
1. 令 V 为 undefined 。
2. 令 A 为
List
中的
CaseClause
项,按源文本顺序排列。
3. 令 found 为 false 。
4. 对 A 中的每个
CaseClause
C ,执行以下操作:
a. 如果 found 为 false ,则:
i. 令 found 为 ?
CaseClauseIsSelected
(C , input )。
b. 如果 found 为 true ,则:
i. 令 R 为
Completion
(
Evaluation
(C ))。
ii. 如果 R .[[Value]] 不是
empty ,则将 V 设为 R .[[Value]] 。
iii. 如果 R 是
中止完成
,则返回 ?
UpdateEmpty
(R , V )。
5. 返回 V 。
CaseBlock
:
{
CaseClauses
opt
DefaultClause
CaseClauses
opt
}
1. 令 V 为 undefined 。
2. 如果存在第一个
CaseClauses
,则:
a. 令 A 为
List
中的
CaseClause
项,按源文本顺序排列。
3. 否则:
a. 令 A 为一个新的空
List
。
4. 令 found 为 false 。
5. 对 A 中的每个
CaseClause
C ,执行以下操作:
a. 如果 found 为 false ,则:
i. 令 found 为 ?
CaseClauseIsSelected
(C , input )。
b. 如果 found 为 true ,则:
i. 令 R 为
Completion
(
Evaluation
(C ))。
ii. 如果 R .[[Value]] 不是
empty ,则将 V 设为 R .[[Value]] 。
iii. 如果 R 是
中止完成
,则返回 ?
UpdateEmpty
(R , V )。
6. 令 foundInB 为 false 。
7. 如果存在第二个
CaseClauses
,则:
a. 令 B 为
List
中的
CaseClause
项,按源文本顺序排列。
8. 否则:
a. 令 B 为一个新的空
List
。
9. 如果 found 为 false ,则:
a. 对 B 中的每个
CaseClause
C ,执行以下操作:
i. 如果 foundInB 为 false ,则:
1. 令 foundInB 为 ?
CaseClauseIsSelected
(C , input )。
ii. 如果 foundInB 为 true ,则:
1. 令 R 为
Completion
(
Evaluation
(
CaseClause
C ))。
2. 如果 R .[[Value]] 不是
empty ,则将 V 设为 R .[[Value]] 。
3. 如果 R 是
中止完成
,则返回 ?
UpdateEmpty
(R , V )。
10. 如果 foundInB 为 true ,则返回 V 。
11. 令 defaultR 为
Completion
(
Evaluation
(
DefaultClause
))。
12. 如果 defaultR .[[Value]] 不是
empty ,则将 V 设为 defaultR .[[Value]] 。
13. 如果 defaultR 是
中止完成
,则返回 ?
UpdateEmpty
(defaultR , V )。
14. 注:以下是第二个
CaseClauses
的另一个完整迭代。
15. 对 B 中的每个
CaseClause
C ,执行以下操作:
a. 令 R 为
Completion
(
Evaluation
(
CaseClause
C ))。
b. 如果 R .[[Value]] 不是
empty ,则将 V 设为 R .[[Value]] 。
c. 如果 R 是
中止完成
,则返回 ?
UpdateEmpty
(R , V )。
16. 返回 V 。
14.12.3 CaseClauseIsSelected ( C , input )
抽象操作 CaseClauseIsSelected 接受参数 C (一个
CaseClause
解析节点
)和 input (一个
ECMAScript 语言值
),并返回
正常完成包含的
布尔值或
中止完成
。它在调用时执行以下步骤:
1.
断言
:C 是
CaseClause
:
case
Expression
:
StatementList
opt
的一个实例。
2. 令 exprRef 为 ?
Evaluation
C 的
Expression
。
3. 令 clauseSelector 为 ?
GetValue
(exprRef )。
4. 返回
IsStrictlyEqual
(input , clauseSelector )。
注
此操作不执行 C 的
StatementList
(如果有)。
CaseBlock
算法使用其返回值来确定要开始执行的
StatementList
。
14.12.4 运行时语义:Evaluation
SwitchStatement
:
switch
(
Expression
)
CaseBlock
1. 令 exprRef 为 ?
Evaluation
(
Expression
)。
2. 令 switchValue 为 ?
GetValue
(exprRef )。
3. 令 oldEnv 为
当前执行上下文
的 LexicalEnvironment。
4. 令 blockEnv 为
NewDeclarativeEnvironment
(oldEnv )。
5. 执行
BlockDeclarationInstantiation
(
CaseBlock
, blockEnv )。
6. 将
当前执行上下文
的 LexicalEnvironment 设置为 blockEnv 。
7. 令 R 为
Completion
(
CaseBlockEvaluation
(
CaseBlock
, switchValue ))。
8. 将
当前执行上下文
的 LexicalEnvironment 设置回 oldEnv 。
9. 返回 R 。
注
无论控制如何离开
SwitchStatement
,LexicalEnvironment 总是恢复到其先前状态。
CaseClause
:
case
Expression
:
1. 返回 empty 。
CaseClause
:
case
Expression
:
StatementList
1. 返回 ?
Evaluation
(
StatementList
)。
DefaultClause
:
default
:
1. 返回 empty 。
DefaultClause
:
default
:
StatementList
1. 返回 ?
Evaluation
(
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
注
如果实现了
B.3.1
中指定的扩展,则此规则的替代定义是必要的。
14.13.2 静态语义:IsLabelledFunction (stmt )
抽象操作 IsLabelledFunction 接受参数 stmt (一个
Statement
解析节点
) 并返回一个布尔值。当调用时执行以下步骤:
1. 如果 stmt 不是一个
LabelledStatement
,返回 false 。
2. 让 item 成为 stmt 的
LabelledItem
。
3. 如果 item 是
LabelledItem
:
FunctionDeclaration
,返回 true 。
4. 让 subStmt 成为 item 的
Statement
。
5. 返回
IsLabelledFunction
(subStmt )。
14.13.3 运行时语义:评估
LabelledStatement
:
LabelIdentifier
:
LabelledItem
1. 返回 ?
LabelledEvaluation
的这个
LabelledStatement
,参数为 « »。
14.13.4 运行时语义:LabelledEvaluation
语法指向操作
LabelledEvaluation 接受参数 labelSet (一个
列表
字符串)并返回一个
正常完成包含
的
ECMAScript 语言值
或一个
突然完成
。它在以下生成中逐步定义:
BreakableStatement
:
IterationStatement
1. 让 stmtResult 成为
Completion
(
LoopEvaluation
的
IterationStatement
,参数为 labelSet )。
2. 如果 stmtResult 是一个
break completion
,则
a. 如果 stmtResult .[[Target]] 是
empty ,则
i. 如果 stmtResult .[[Value]]
是
empty ,则将 stmtResult 设置为
NormalCompletion
(undefined )。
ii. 否则,将 stmtResult 设置为
NormalCompletion
(stmtResult .[[Value]] )。
3. 返回 ? stmtResult 。
BreakableStatement
:
SwitchStatement
1. 让 stmtResult 成为
Completion
(
Evaluation
的
SwitchStatement
)。
2. 如果 stmtResult 是一个
break completion
,则
a. 如果 stmtResult .[[Target]] 是
empty ,则
i. 如果 stmtResult .[[Value]]
是
empty ,则将 stmtResult 设置为
NormalCompletion
(undefined )。
ii. 否则,将 stmtResult 设置为
NormalCompletion
(stmtResult .[[Value]] )。
3. 返回 ? stmtResult 。
注 1
LabelledStatement
:
LabelIdentifier
:
LabelledItem
1. 让 label 成为
StringValue
的
LabelIdentifier
。
2. 让 newLabelSet 成为
列表连接
的 labelSet 和 « label »。
3. 让 stmtResult 成为
Completion
(
LabelledEvaluation
的
LabelledItem
,参数为 newLabelSet )。
4. 如果 stmtResult 是一个
break completion
并且 stmtResult .[[Target]] 是 label ,则
a. 将 stmtResult 设置为
NormalCompletion
(stmtResult .[[Value]] )。
5. 返回 ? stmtResult 。
LabelledItem
:
FunctionDeclaration
1. 返回 ?
Evaluation
的
FunctionDeclaration
。
Statement
:
BlockStatement
VariableStatement
EmptyStatement
ExpressionStatement
IfStatement
ContinueStatement
BreakStatement
ReturnStatement
WithStatement
ThrowStatement
TryStatement
DebuggerStatement
1. 返回 ?
Evaluation
的
Statement
。
注 2
Statement
的唯一两个在 LabelledEvaluation 中具有特殊语义的生成是
BreakableStatement
和
LabelledStatement
。
14.14 throw 语句
语法
ThrowStatement
[Yield, Await]
:
throw
[此处不能有
行终止符
]
表达式
[+In, ?Yield, ?Await]
;
14.14.1 运行时语义:求值
ThrowStatement
:
throw
表达式
;
1. 令 exprRef 为 ?
Evaluation
的
表达式 。
2. 令 exprValue 为 ?
GetValue
(exprRef )。
3. 返回
ThrowCompletion
(exprValue )。
14.15 try 语句
语法
TryStatement
[Yield, Await, Return]
:
try
Block
[?Yield, ?Await, ?Return]
Catch
[?Yield, ?Await, ?Return]
try
Block
[?Yield, ?Await, ?Return]
Finally
[?Yield, ?Await, ?Return]
try
Block
[?Yield, ?Await, ?Return]
Catch
[?Yield, ?Await, ?Return]
Finally
[?Yield, ?Await, ?Return]
Catch
[Yield, Await, Return]
:
catch
(
CatchParameter
[?Yield, ?Await]
)
Block
[?Yield, ?Await, ?Return]
catch
Block
[?Yield, ?Await, ?Return]
Finally
[Yield, Await, Return]
:
finally
Block
[?Yield, ?Await, ?Return]
CatchParameter
[Yield, Await]
:
BindingIdentifier
[?Yield, ?Await]
BindingPattern
[?Yield, ?Await]
注
try 语句包含可能发生异常的代码块,如运行时错误或 throw 语句。catch 子句提供异常处理代码。当 catch 子句捕获异常时,其
CatchParameter
绑定到该异常。
14.15.1 静态语义:早期错误
Catch
:
catch
(
CatchParameter
)
Block
注
对于此生成规则的替代静态语义定义,见
B.3.4
。
14.15.2 运行时语义:CatchClauseEvaluation
CatchClauseEvaluation 是一个带有参数 thrownValue (一个 ECMAScript 语言值)的语法直接操作,返回一个包含 ECMAScript
语言值的正常完成记录或一个中断完成记录。它在以下生成规则中定义:
Catch
:
catch
(
CatchParameter
)
Block
1. 令 oldEnv 为当前执行上下文的 LexicalEnvironment。
2. 令 catchEnv 为
NewDeclarativeEnvironment
(oldEnv )。
3. 对于
BoundNames
的
CatchParameter
中的每个元素 argName ,执行
a. 执行
! catchEnv .CreateMutableBinding(argName , false )。
4. 将当前执行上下文的 LexicalEnvironment 设置为 catchEnv 。
5. 令 status 为
Completion
(
BindingInitialization
的
CatchParameter
,参数为 thrownValue 和 catchEnv )。
6. 如果 status 是一个中断完成,则
a. 将当前执行上下文的 LexicalEnvironment 设置为 oldEnv 。
b. 返回 ? status 。
7. 令 B 为
Completion
(
Evaluation
的
Block
)。
8. 将当前执行上下文的 LexicalEnvironment 设置为 oldEnv 。
9. 返回 ? B 。
Catch
:
catch
Block
1. 返回 ?
Evaluation
的
Block
。
注
无论控制如何离开
Block
,LexicalEnvironment 总是恢复到原来的状态。
14.15.3 运行时语义:Evaluation
TryStatement
:
try
Block
Catch
1. 令 B 为
Completion
(
Evaluation
的
Block
)。
2. 如果 B 是一个
throw completion
,令 C 为
Completion
(
CatchClauseEvaluation
的
Catch
,参数为 B .[[Value]] )。
3. 否则,令 C 为 B 。
4. 返回 ?
UpdateEmpty
(C , undefined )。
TryStatement
:
try
Block
Finally
1. 令 B 为
Completion
(
Evaluation
的
Block
)。
2. 令 F 为
Completion
(
Evaluation
的
Finally
)。
3. 如果 F 是一个
normal completion
,则将 F 设置为 B 。
4. 返回 ?
UpdateEmpty
(F , undefined )。
TryStatement
:
try
Block
Catch
Finally
1. 令 B 为
Completion
(
Evaluation
的
Block
)。
2. 如果 B 是一个
throw completion
,令 C 为
Completion
(
CatchClauseEvaluation
的
Catch
,参数为 B .[[Value]] )。
3. 否则,令 C 为 B 。
4. 令 F 为
Completion
(
Evaluation
的
Finally
)。
5. 如果 F 是一个
normal completion
,则将 F 设置为 C 。
6. 返回 ?
UpdateEmpty
(F , undefined )。
14.16 debugger
语句
句法
DebuggerStatement
:
debugger
;
14.16.1 运行时语义:Evaluation
注
执行
DebuggerStatement
时,在调试器下运行时可能会触发断点。如果调试器不存在或未激活,此语句不会产生可观察到的效果。
DebuggerStatement
:
debugger
;
1. 如果一个
实现定义
的调试设施可用且已启用,则
a. 执行一个
实现定义
的调试动作。
b. 返回一个新的
实现定义
的
Completion
Record
。
2. 否则,
a. 返回 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 不接受参数并返回一个布尔值。它分段定义在以下产生式上:
ObjectBindingPattern
:
{
}
{
BindingRestProperty
}
返回 false 。
ObjectBindingPattern
:
{
BindingPropertyList
,
BindingRestProperty
}
返回 ContainsExpression
的 BindingPropertyList 。
ArrayBindingPattern
:
[
Elision opt
]
返回 false 。
ArrayBindingPattern
:
[
Elision opt
BindingRestElement
]
返回 ContainsExpression
的 BindingRestElement 。
ArrayBindingPattern
:
[
BindingElementList
,
Elision opt
]
返回 ContainsExpression
的 BindingElementList 。
ArrayBindingPattern
:
[
BindingElementList
,
Elision opt
BindingRestElement
]
令 has 为 ContainsExpression
的 BindingElementList 。
如果 has 为 true ,则返回 true 。
返回 ContainsExpression
的 BindingRestElement 。
BindingPropertyList
:
BindingPropertyList
,
BindingProperty
令 has 为 ContainsExpression
的 BindingPropertyList 。
如果 has 为 true ,则返回 true 。
返回 ContainsExpression
的 BindingProperty 。
BindingElementList
:
BindingElementList
,
BindingElisionElement
令 has 为 ContainsExpression
的 BindingElementList 。
如果 has 为 true ,则返回 true 。
返回 ContainsExpression
的 BindingElisionElement 。
BindingElisionElement
:
Elision opt
BindingElement
返回 ContainsExpression
的 BindingElement 。
BindingProperty
:
PropertyName
:
BindingElement
令 has 为 IsComputedPropertyKey
的 PropertyName 。
如果 has 为 true ,则返回 true 。
返回 ContainsExpression
的 BindingElement 。
BindingElement
:
BindingPattern
Initializer
返回 true 。
SingleNameBinding
:
BindingIdentifier
返回 false 。
SingleNameBinding
:
BindingIdentifier
Initializer
返回 true 。
BindingRestElement
:
...
BindingIdentifier
返回 false 。
BindingRestElement
:
...
BindingPattern
返回 ContainsExpression
的 BindingPattern 。
FormalParameters
:
[empty]
返回 false 。
FormalParameters
:
FormalParameterList
,
FunctionRestParameter
如果 ContainsExpression
的 FormalParameterList 为
true ,则返回 true 。
返回 ContainsExpression
的 FunctionRestParameter 。
FormalParameterList
:
FormalParameterList
,
FormalParameter
如果 ContainsExpression
的 FormalParameterList 为
true ,则返回 true 。
返回 ContainsExpression
的 FormalParameter 。
ArrowParameters
:
BindingIdentifier
返回 false 。
ArrowParameters
:
CoverParenthesizedExpressionAndArrowParameterList
令 formals 为 ArrowFormalParameters ,它被
涵盖 的 CoverParenthesizedExpressionAndArrowParameterList 。
返回 ContainsExpression
的 formals 。
AsyncArrowBindingIdentifier
:
BindingIdentifier
返回 false 。
15.1.3 静态语义:IsSimpleParameterList
语法导向操作
IsSimpleParameterList 不接受参数并返回一个布尔值。它分段定义在以下产生式上:
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
如果 IsSimpleParameterList
的 FormalParameterList 为
false ,则返回 false 。
返回 IsSimpleParameterList
的 FormalParameter 。
FormalParameter
:
BindingElement
返回 IsSimpleParameterList
的 BindingElement 。
ArrowParameters
:
BindingIdentifier
返回 true 。
ArrowParameters
:
CoverParenthesizedExpressionAndArrowParameterList
令 formals 为 ArrowFormalParameters ,它被
涵盖 的 CoverParenthesizedExpressionAndArrowParameterList 。
返回 IsSimpleParameterList
的 formals 。
AsyncArrowBindingIdentifier
:
BindingIdentifier
返回 true 。
CoverCallExpressionAndAsyncArrowHead
:
MemberExpression
Arguments
令 head 为 AsyncArrowHead ,它被 涵盖 的 CoverCallExpressionAndAsyncArrowHead 。
返回 IsSimpleParameterList
的 head 。
15.1.4 静态语义:HasInitializer
语法导向操作
HasInitializer 不接受参数并返回一个布尔值。它分段定义在以下产生式上:
BindingElement
:
BindingPattern
返回 false 。
BindingElement
:
BindingPattern
Initializer
返回 true 。
SingleNameBinding
:
BindingIdentifier
返回 false 。
SingleNameBinding
:
BindingIdentifier
Initializer
返回 true 。
FormalParameterList
:
FormalParameterList
,
FormalParameter
如果 HasInitializer 的
FormalParameterList 为
true ,则返回 true 。
返回 HasInitializer 的
FormalParameter 。
15.1.5 静态语义:ExpectedArgumentCount
语法导向操作
ExpectedArgumentCount 不接受参数并返回一个 整数 。它分段定义在以下产生式上:
FormalParameters
:
[empty]
FunctionRestParameter
返回 0。
FormalParameters
:
FormalParameterList
,
FunctionRestParameter
返回 ExpectedArgumentCount
的 FormalParameterList 。
注
FormalParameterList 的
ExpectedArgumentCount 是
FormalParameters 中在 rest
参数或第一个带初始化器的
FormalParameter 左边的参数数量。
FormalParameter
没有初始化器允许在第一个带初始化器的参数之后,但这些参数被认为是可选的,并且其默认值为 undefined 。
FormalParameterList
:
FormalParameter
如果 HasInitializer 的
FormalParameter 为
true ,返回 0。
返回 1。
FormalParameterList
:
FormalParameterList
,
FormalParameter
令 count 为 ExpectedArgumentCount
的 FormalParameterList 。
如果 HasInitializer 的
FormalParameterList 为
true 或者 HasInitializer 的
FormalParameter 为
true ,则返回 count 。
返回 count + 1。
ArrowParameters
:
BindingIdentifier
返回 1。
ArrowParameters
:
CoverParenthesizedExpressionAndArrowParameterList
令 formals 为 ArrowFormalParameters ,它被
涵盖 的 CoverParenthesizedExpressionAndArrowParameterList 。
返回 ExpectedArgumentCount
的 formals 。
PropertySetParameterList
:
FormalParameter
如果 HasInitializer 的
FormalParameter 为
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
}
注
LexicallyDeclaredNames
不包括使用 var 或函数声明绑定的标识符。
FunctionBody
:
FunctionStatementList
15.2.2 静态语义:FunctionBodyContainsUseStrict
syntax-directed
operation
FunctionBodyContainsUseStrict 不接受参数并返回一个布尔值。其定义如下:
FunctionBody
:
FunctionStatementList
1.
如果
Directive Prologue
的
FunctionBody
包含
Use Strict Directive
,则返回 true ;否则,返回 false 。
15.2.3 运行时语义:EvaluateFunctionBody
syntax-directed
operation
EvaluateFunctionBody 接受参数 functionObject (一个 ECMAScript
function object
)和 argumentsList (一个
List
)并返回一个
normal completion
containing
一个
ECMAScript language value
或一个
abrupt completion
。其定义如下:
FunctionBody
:
FunctionStatementList
1.
执行 ?
FunctionDeclarationInstantiation
(functionObject , argumentsList )。
2.
返回 ?
Evaluation
的
FunctionStatementList
。
15.2.4 运行时语义:InstantiateOrdinaryFunctionObject
syntax-directed
operation
InstantiateOrdinaryFunctionObject 接受参数 env (一个
Environment Record
)和 privateEnv (一个
PrivateEnvironment Record
或 null )并返回一个 ECMAScript
function object
。其定义如下:
FunctionDeclaration
:
function
BindingIdentifier
(
FormalParameters
)
{
FunctionBody
}
1.
令 name 为
StringValue
的
BindingIdentifier
。
2.
令 sourceText 为
source text
matched by
的
FunctionDeclaration
。
3.
令 F 为
OrdinaryFunctionCreate
(
%Function.prototype%
,sourceText ,
FormalParameters
,
FunctionBody
,non-lexical-this ,env ,privateEnv )。
4.
执行
SetFunctionName
(F ,name )。
5.
执行
MakeConstructor
(F )。
6.
返回 F 。
FunctionDeclaration
:
function
(
FormalParameters
)
{
FunctionBody
}
1.
令 sourceText 为
source text
matched by
的
FunctionDeclaration
。
2.
令 F 为
OrdinaryFunctionCreate
(
%Function.prototype%
,sourceText ,
FormalParameters
,
FunctionBody
,non-lexical-this ,env ,privateEnv )。
3.
执行
SetFunctionName
(F ,"default" )。
4.
执行
MakeConstructor
(F )。
5.
返回 F 。
注
匿名的
FunctionDeclaration
只能作为 export default
声明的一部分出现,因此其函数代码始终是
strict mode code
。
15.2.5 运行时语义:InstantiateOrdinaryFunctionExpression
syntax-directed
operation
InstantiateOrdinaryFunctionExpression 接受可选参数 name (一个
property key
或一个
Private Name
)并返回一个 ECMAScript
function object
。其定义如下:
FunctionExpression
:
function
(
FormalParameters
)
{
FunctionBody
}
1.
如果 name 不存在,则将 name 设置为空字符串。
2.
令 env 为当前执行上下文的词法环境。
3.
令 privateEnv 为当前执行上下文的私有环境。
4.
令 sourceText 为
source text
matched by
的
FunctionExpression
。
5.
令 closure 为
OrdinaryFunctionCreate
(
%Function.prototype%
,sourceText ,
FormalParameters
,
FunctionBody
,non-lexical-this ,env ,privateEnv )。
6.
执行
SetFunctionName
(closure ,name )。
7.
执行
MakeConstructor
(closure )。
8.
返回 closure 。
FunctionExpression
:
function
BindingIdentifier
(
FormalParameters
)
{
FunctionBody
}
1.
断言
:name 不存在。
2.
设置 name 为
StringValue
的
BindingIdentifier
。
3.
令 outerEnv 为当前执行上下文的词法环境。
4.
令 funcEnv 为
NewDeclarativeEnvironment
(outerEnv )。
5.
执行 ! funcEnv .CreateImmutableBinding(name , false )。
6.
令 privateEnv 为当前执行上下文的私有环境。
7.
令 sourceText 为
source text
matched by
的
FunctionExpression
。
8.
令 closure 为
OrdinaryFunctionCreate
(
%Function.prototype%
,sourceText ,
FormalParameters
,
FunctionBody
,non-lexical-this ,funcEnv ,privateEnv )。
9.
执行
SetFunctionName
(closure ,name )。
10.
执行
MakeConstructor
(closure )。
11.
执行 ! funcEnv .InitializeBinding(name , closure )。
12.
返回 closure 。
注
15.2.6 运行时语义:Evaluation
FunctionDeclaration
:
function
BindingIdentifier
(
FormalParameters
)
{
FunctionBody
}
1.
返回 empty 。
注 1
FunctionDeclaration
:
function
(
FormalParameters
)
{
FunctionBody
}
1.
返回 empty 。
FunctionExpression
:
function
BindingIdentifier
opt
(
FormalParameters
)
{
FunctionBody
}
1.
返回
InstantiateOrdinaryFunctionExpression
的
FunctionExpression
。
注 2
使用
FunctionDeclaration
或
FunctionExpression
定义的每个函数会自动创建一个 "prototype" 属性,以便函数可以作为
constructor
使用。
FunctionStatementList
:
[empty]
1.
返回 undefined 。
15.3 箭头函数定义
语法
ArrowFunction
[In, Yield, Await]
:
ArrowParameters
[?Yield, ?Await]
[no
LineTerminator
here]
=>
ConciseBody
[?In]
ArrowParameters
[Yield, Await]
:
BindingIdentifier
[?Yield, ?Await]
CoverParenthesizedExpressionAndArrowParameterList
[?Yield, ?Await]
ConciseBody
[In]
:
[lookahead ≠ { ]
ExpressionBody
[?In, ~Await]
{
FunctionBody
[~Yield, ~Await]
}
ExpressionBody
[In, Await]
:
AssignmentExpression
[?In, ~Yield, ?Await]
补充语法
处理生产式的实例时
ArrowParameters
[Yield, Await]
:
CoverParenthesizedExpressionAndArrowParameterList
[?Yield, ?Await]
CoverParenthesizedExpressionAndArrowParameterList
的解释使用以下语法进行细化:
ArrowFormalParameters
[Yield, Await]
:
(
UniqueFormalParameters
[?Yield, ?Await]
)
15.3.1 静态语义:早期错误
ArrowFunction
:
ArrowParameters
=>
ConciseBody
ArrowParameters
:
CoverParenthesizedExpressionAndArrowParameterList
15.3.2 静态语义:ConciseBodyContainsUseStrict
syntax-directed
operation
ConciseBodyContainsUseStrict 不接受参数并返回一个布尔值。其定义如下:
ConciseBody
:
ExpressionBody
1.
返回 false 。
ConciseBody
:
{
FunctionBody
}
1.
返回
FunctionBodyContainsUseStrict
的
FunctionBody
。
15.3.3 运行时语义:EvaluateConciseBody
syntax-directed
operation
EvaluateConciseBody 接受参数 functionObject (一个 ECMAScript
函数对象
)和 argumentsList (一个
列表
,包含
ECMAScript 语言值
)并返回一个
完成记录
,其中包含一个
ECMAScript 语言值
或一个
异常完成
。其定义如下:
ConciseBody
:
ExpressionBody
1.
执行 ?
FunctionDeclarationInstantiation
(functionObject ,argumentsList )。
2.
返回 ?
Evaluation
的
ExpressionBody
。
15.3.4 运行时语义:InstantiateArrowFunctionExpression
syntax-directed
operation
InstantiateArrowFunctionExpression 接受可选参数 name (一个
属性键
或一个
私有名称
)并返回一个 ECMAScript
函数对象
。其定义如下:
ArrowFunction
:
ArrowParameters
=>
ConciseBody
1.
如果 name 不存在,将 name 设置为 "" 。
2.
令 env 为当前执行上下文的词法环境。
3.
令 privateEnv 为当前执行上下文的私有环境。
4.
令 sourceText 为
source text
matched by
的
ArrowFunction
。
5.
令 closure 为
OrdinaryFunctionCreate
(
%Function.prototype%
,sourceText ,
ArrowParameters
,
ConciseBody
,lexical-this ,env ,privateEnv )。
6.
执行
SetFunctionName
(closure ,name )。
7.
返回 closure 。
注
ArrowFunction
不定义 arguments
,super
,this
或 new.target
的本地绑定。在
ArrowFunction
内对 arguments
,super
,this
或 new.target
的任何引用必须解析为词法上封闭的环境中的绑定。通常,这将是紧密封闭函数的函数环境。即使
ArrowFunction
可能包含对 super
的引用,在步骤
5
中创建的
函数对象
不会通过执行
MakeMethod
变成一个方法。一个引用 super
的
ArrowFunction
总是包含在一个非
ArrowFunction
中,实现 super
所需的状态可以通过
函数对象
所捕获的 env 访问
ArrowFunction
。
15.3.5 运行时语义:Evaluation
ArrowFunction
:
ArrowParameters
=>
ConciseBody
1.
返回
InstantiateArrowFunctionExpression
的
ArrowFunction
。
ExpressionBody
:
AssignmentExpression
1.
令 exprRef 为 ?
Evaluation
的
AssignmentExpression
。
2.
令 exprValue 为 ?
GetValue
(exprRef )。
3.
返回
Completion Record
{ [[Type]] :
return ,[[Value]] :exprValue ,[[Target]] :
empty }。
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 不接受任何参数并返回一个布尔值。它在以下生成式上逐段定义:
MethodDefinition
:
ClassElementName
(
UniqueFormalParameters
)
{
FunctionBody
}
1. 如果
UniqueFormalParameters
包含
SuperCall
是 true ,则返回 true 。
2. 返回
FunctionBody
包含
SuperCall
。
MethodDefinition
:
get
ClassElementName
(
)
{
FunctionBody
}
1. 返回
FunctionBody
包含
SuperCall
。
MethodDefinition
:
set
ClassElementName
(
PropertySetParameterList
)
{
FunctionBody
}
1. 如果
PropertySetParameterList
包含
SuperCall
是 true ,则返回 true 。
2. 返回
FunctionBody
包含
SuperCall
。
GeneratorMethod
:
*
ClassElementName
(
UniqueFormalParameters
)
{
GeneratorBody
}
1. 如果
UniqueFormalParameters
包含
SuperCall
是 true ,则返回 true 。
2. 返回
GeneratorBody
包含
SuperCall
。
AsyncGeneratorMethod
:
async
*
ClassElementName
(
UniqueFormalParameters
)
{
AsyncGeneratorBody
}
1. 如果
UniqueFormalParameters
包含
SuperCall
是 true ,则返回 true 。
2. 返回
AsyncGeneratorBody
包含
SuperCall
。
AsyncMethod
:
async
ClassElementName
(
UniqueFormalParameters
)
{
AsyncFunctionBody
}
1. 如果
UniqueFormalParameters
包含
SuperCall
是 true ,则返回 true 。
2. 返回
AsyncFunctionBody
包含
SuperCall
。
15.4.3 静态语义:SpecialMethod
语法指向操作 SpecialMethod 不接受任何参数并返回一个布尔值。它在以下生成式上逐段定义:
MethodDefinition
:
ClassElementName
(
UniqueFormalParameters
)
{
FunctionBody
}
1. 返回 false 。
MethodDefinition
:
GeneratorMethod
AsyncMethod
AsyncGeneratorMethod
get
ClassElementName
(
)
{
FunctionBody
}
set
ClassElementName
(
PropertySetParameterList
)
{
FunctionBody
}
1. 返回 true 。
15.4.4 运行时语义:DefineMethod
语法指向操作 DefineMethod 接受参数 object(一个对象)和可选参数 functionPrototype(一个对象),并返回一个包含字段 [[Key]](一个属性键)和 [[Closure]](一个
ECMAScript 函数对象)的 Record 的正常完成,或一个中断完成。它在以下生成式上逐段定义:
MethodDefinition
:
ClassElementName
(
UniqueFormalParameters
)
{
FunctionBody
}
1. 令 propKey 为 ?
Evaluation
的
ClassElementName
的结果。
2. 令 env 为
当前执行上下文
的 LexicalEnvironment。
3. 令 privateEnv 为
当前执行上下文
的 PrivateEnvironment。
4. 如果 functionPrototype 存在,则:
a. 令 prototype 为 functionPrototype。
5. 否则:
a. 令 prototype 为
%Function.prototype%
。
6. 令 sourceText 为
由
MethodDefinition
匹配的源文本。
7. 令 closure 为
OrdinaryFunctionCreate
(prototype, sourceText,
UniqueFormalParameters
,
FunctionBody
, non-lexical-this, env, privateEnv)。
8. 执行
MakeMethod
(closure, object)。
9. 返回 { [[Key]]: propKey, [[Closure]]: closure } 的 Record。
15.4.5 运行时语义:MethodDefinitionEvaluation
语法指向操作 MethodDefinitionEvaluation 接受参数 object(一个对象)和 enumerable(一个布尔值),并返回包含一个 PrivateElement 或 unused
的正常完成,或一个中断完成。它在以下生成式上逐段定义:
MethodDefinition
:
ClassElementName
(
UniqueFormalParameters
)
{
FunctionBody
}
1. 令 methodDef 为 ?
DefineMethod
的结果。
2. 执行
SetFunctionName
(methodDef.[[Closure]], methodDef.[[Key]])。
3. 返回 ?
DefineMethodProperty
(object, methodDef.[[Key]], methodDef.[[Closure]], enumerable)。
MethodDefinition
:
get
ClassElementName
(
)
{
FunctionBody
}
1. 令 propKey 为 ?
Evaluation
的
ClassElementName
的结果。
2. 令 env 为
当前执行上下文
的 LexicalEnvironment。
3. 令 privateEnv 为
当前执行上下文
的 PrivateEnvironment。
4. 令 sourceText 为
由
MethodDefinition
匹配的源文本。
5. 令 formalParameterList 为生产式
FormalParameters
:
[empty]
的实例。
6. 令 closure 为
OrdinaryFunctionCreate
(
%Function.prototype%
, sourceText, formalParameterList,
FunctionBody
, non-lexical-this, env, privateEnv)。
7. 执行
MakeMethod
(closure, object)。
8. 执行
SetFunctionName
(closure, propKey, "get")。
9. 如果 propKey 是一个
私有名称
,则:
a. 返回 { [[Key]]: propKey, [[Kind]]: accessor, [[Get]]: closure,
[[Set]]: undefined } 的 PrivateElement。
10. 否则:
a. 令 desc 为 PropertyDescriptor { [[Get]]: closure, [[Enumerable]]:
enumerable, [[Configurable]]: true }。
b. 执行 ?
DefinePropertyOrThrow
(object, propKey, desc)。
c. 返回 unused。
MethodDefinition
:
set
ClassElementName
(
PropertySetParameterList
)
{
FunctionBody
}
1. 令 propKey 为 ?
Evaluation
的
ClassElementName
的结果。
2. 令 env 为
当前执行上下文
的 LexicalEnvironment。
3. 令 privateEnv 为
当前执行上下文
的 PrivateEnvironment。
4. 令 sourceText 为
由
MethodDefinition
匹配的源文本。
5. 令 closure 为
OrdinaryFunctionCreate
(
%Function.prototype%
, sourceText,
PropertySetParameterList
,
FunctionBody
, non-lexical-this, env, privateEnv)。
6. 执行
MakeMethod
(closure, object)。
7. 执行
SetFunctionName
(closure, propKey, "set")。
8. 如果 propKey 是一个
私有名称
,则:
a. 返回 { [[Key]]: propKey, [[Kind]]: accessor, [[Get]]: undefined,
[[Set]]: closure } 的 PrivateElement。
9. 否则:
a. 令 desc 为 PropertyDescriptor { [[Set]]: closure, [[Enumerable]]:
enumerable, [[Configurable]]: true }。
b. 执行 ?
DefinePropertyOrThrow
(object, propKey, desc)。
c. 返回 unused。
GeneratorMethod
:
*
ClassElementName
(
UniqueFormalParameters
)
{
GeneratorBody
}
1. 令 propKey 为 ?
Evaluation
的
ClassElementName
的结果。
2. 令 env 为
当前执行上下文
的 LexicalEnvironment。
3. 令 privateEnv 为
当前执行上下文
的 PrivateEnvironment。
4. 令 sourceText 为
由
GeneratorMethod
匹配的源文本。
5. 令 closure 为
OrdinaryFunctionCreate
(
%GeneratorFunction.prototype%
, sourceText,
UniqueFormalParameters
,
GeneratorBody
, non-lexical-this, env, privateEnv)。
6. 执行
MakeMethod
(closure, object)。
7. 执行
SetFunctionName
(closure, propKey)。
8. 令 prototype 为
OrdinaryObjectCreate
(
%GeneratorFunction.prototype.prototype%
)。
9. 执行 !
DefinePropertyOrThrow
(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true,
[[Enumerable]]: false, [[Configurable]]: false })。
10. 返回 ?
DefineMethodProperty
(object, propKey, closure, enumerable)。
AsyncGeneratorMethod
:
async
*
ClassElementName
(
UniqueFormalParameters
)
{
AsyncGeneratorBody
}
1. 令 propKey 为 ?
Evaluation
的
ClassElementName
的结果。
2. 令 env 为
当前执行上下文
的 LexicalEnvironment。
3. 令 privateEnv 为
当前执行上下文
的 PrivateEnvironment。
4. 令 sourceText 为
由
AsyncGeneratorMethod
匹配的源文本。
5. 令 closure 为
OrdinaryFunctionCreate
(
%AsyncGeneratorFunction.prototype%
, sourceText,
UniqueFormalParameters
,
AsyncGeneratorBody
, non-lexical-this, env, privateEnv)。
6. 执行
MakeMethod
(closure, object)。
7. 执行
SetFunctionName
(closure, propKey)。
8. 令 prototype 为
OrdinaryObjectCreate
(
%AsyncGeneratorFunction.prototype.prototype%
)。
9. 执行 !
DefinePropertyOrThrow
(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true,
[[Enumerable]]: false, [[Configurable]]: false })。
10. 返回 ?
DefineMethodProperty
(object, propKey, closure, enumerable)。
AsyncMethod
:
async
ClassElementName
(
UniqueFormalParameters
)
{
AsyncFunctionBody
}
1. 令 propKey 为 ?
Evaluation
的
ClassElementName
的结果。
2. 令 env 为
当前执行上下文
的 LexicalEnvironment。
3. 令 privateEnv 为
当前执行上下文
的 PrivateEnvironment。
4. 令 sourceText 为
由
AsyncMethod
匹配的源文本。
5. 令 closure 为
OrdinaryFunctionCreate
(
%AsyncFunction.prototype%
, sourceText,
UniqueFormalParameters
,
AsyncFunctionBody
, non-lexical-this, env, privateEnv)。
6. 执行
MakeMethod
(closure, object)。
7. 执行
SetFunctionName
(closure, propKey)。
8. 返回 ?
DefineMethodProperty
(object, propKey, closure, enumerable)。
15.5 生成器函数定义
语法
GeneratorDeclaration [Yield,
Await, Default] :
function
*
BindingIdentifier [?Yield,
?Await]
(
FormalParameters [+Yield,
~Await]
)
{
GeneratorBody
}
[+Default]
function
*
(
FormalParameters [+Yield,
~Await]
)
{
GeneratorBody
}
GeneratorExpression
:
function
*
BindingIdentifier [+Yield,
~Await] opt
(
FormalParameters [+Yield,
~Await]
)
{
GeneratorBody
}
GeneratorMethod [Yield,
Await] :
*
ClassElementName [?Yield,
?Await]
(
UniqueFormalParameters [+Yield,
~Await]
)
{
GeneratorBody
}
GeneratorBody
:
FunctionBody [+Yield,
~Await]
YieldExpression [In,
Await] :
yield
yield
[no LineTerminator
here]
AssignmentExpression [?In,
+Yield, ?Await]
yield
[no LineTerminator
here]
*
AssignmentExpression [?In,
+Yield, ?Await]
注 1
注 2
注 3
与生成器相关的 抽象操作 定义在
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 (一个
列表 ,包含 ECMAScript 语言值 ),
并返回一个 抛出完成记录
或一个 返回完成记录 。
它的定义分为以下几个步骤:
GeneratorBody
: FunctionBody
1. 执行 ? FunctionDeclarationInstantiation (functionObject ,
argumentsList )。
2. 令 G 为 ? OrdinaryCreateFromConstructor (functionObject ,
"%GeneratorFunction.prototype.prototype%" ,« [[GeneratorState]] , [[GeneratorContext]] , [[GeneratorBrand]] »)。
3. 将 G .[[GeneratorBrand]] 设置为
empty 。
4. 执行 GeneratorStart (G ,
FunctionBody )。
5. 返回 完成记录
{ [[Type]] : return , [[Value]] :
G , [[Target]] :
empty }。
15.5.3 运行时语义:InstantiateGeneratorFunctionObject
语法导向操作 InstantiateGeneratorFunctionObject
接受两个参数:env (一个 环境记录 )和 privateEnv (一个
私有环境记录 或
null ),
并返回一个 ECMAScript 函数对象 。它的定义分为以下几个步骤:
GeneratorDeclaration
:
function
*
BindingIdentifier
(
FormalParameters
)
{
GeneratorBody
}
1. 令 name 为 StringValue 的
BindingIdentifier 。
2. 令 sourceText 为与 GeneratorDeclaration
匹配的
GeneratorDeclaration 的源文本。
3. 令 F 为 OrdinaryFunctionCreate (%GeneratorFunction.prototype% ,
sourceText ,FormalParameters ,GeneratorBody ,
non-lexical-this ,env ,privateEnv )。
4. 执行 SetFunctionName (F ,
name )。
5. 令 prototype 为 OrdinaryObjectCreate (%GeneratorFunction.prototype.prototype% ).
6. 执行 ! DefinePropertyOrThrow (F ,
"prototype" ,属性描述符 { [[Value]] :
prototype ,[[Writable]] : true ,[[Enumerable]] : false ,[[Configurable]] : false })。
7. 返回 F 。
GeneratorDeclaration
:
function
*
(
FormalParameters
)
{
GeneratorBody
}
1. 令 sourceText 为与 GeneratorDeclaration
匹配的
GeneratorDeclaration 的源文本。
2. 令 F 为 OrdinaryFunctionCreate (%GeneratorFunction.prototype% ,
sourceText ,FormalParameters ,GeneratorBody ,
non-lexical-this ,env ,privateEnv )。
3. 执行 SetFunctionName (F ,
"default" )。
4. 令 prototype 为 OrdinaryObjectCreate (%GeneratorFunction.prototype.prototype% ).
5. 执行 ! DefinePropertyOrThrow (F ,
"prototype" ,属性描述符 { [[Value]] :
prototype ,[[Writable]] : true ,[[Enumerable]] : false ,[[Configurable]] : false })。
6. 返回 F 。
注
匿名的 GeneratorDeclaration 只能作为
export default
声明的一部分出现,因此其函数代码始终是 严格模式代码 。
15.5.4 运行时语义:实例化生成器函数表达式
语法导向操作
实例化生成器函数表达式接收一个可选参数 name (一个
属性键
或一个
私有名称
)并返回一个 ECMAScript
函数对象
。其定义如下:
GeneratorExpression
:
function
*
(
FormalParameters
)
{
GeneratorBody
}
如果 name 不存在,将 name 设为空字符串 "" 。
令 env 为当前运行执行上下文的
词法环境
。
令 privateEnv 为当前运行执行上下文的
私有环境
。
令 sourceText 为与
语法导向操作
GeneratorExpression
匹配的源文本。
令 closure 为
OrdinaryFunctionCreate
(
%GeneratorFunction.prototype%
,
sourceText ,
FormalParameters
,
GeneratorBody
,
non-lexical-this , env , privateEnv )。
执行
SetFunctionName
(closure , name )。
令 prototype 为
OrdinaryObjectCreate
(
%GeneratorFunction.prototype.prototype%
)。
执行
DefinePropertyOrThrow
(closure , "prototype" , PropertyDescriptor { [[Value]] : prototype , [[Writable]] :
true , [[Enumerable]] : false , [[Configurable]] : false })。
返回 closure 。
15.5.5 运行时语义:求值
GeneratorExpression
:
function
*
BindingIdentifier
opt
(
FormalParameters
)
{
GeneratorBody
}
1. 返回
InstantiateGeneratorFunctionExpression
的
GeneratorExpression
。
YieldExpression
:
yield
1. 返回 ?
Yield
(undefined )。
YieldExpression
:
yield
AssignmentExpression
1. 令 exprRef 为 ?
Evaluation
的
AssignmentExpression
。
2. 令 value 为 ?
GetValue
(exprRef )。
3. 返回 ?
Yield
(value )。
YieldExpression
:
yield
*
AssignmentExpression
1. 令 generatorKind 为
GetGeneratorKind
()。
2. 令 exprRef 为 ?
Evaluation
的
AssignmentExpression
。
3. 令 value 为 ?
GetValue
(exprRef )。
4. 令 iteratorRecord 为 ?
GetIterator
(value , generatorKind )。
5. 令 iterator 为 iteratorRecord .[[Iterator]] 。
6. 令 received 为
NormalCompletion
(undefined )。
7. 重复,直到:
a. 如果 received 是
正常完成
,则
i. 令 innerResult 为 ?
Call
(iteratorRecord .[[NextMethod]] ,
iteratorRecord .[[Iterator]] , « received .[[Value]] »)。
ii. 如果 generatorKind 是
async ,将 innerResult 设为 ?
Await
(innerResult )。
iii. 如果 innerResult
不是对象
,抛出
TypeError 异常。
iv. 令 done 为 ?
IteratorComplete
(innerResult )。
v. 如果 done 为 true ,则
1. 返回 ?
IteratorValue
(innerResult )。
vi. 如果 generatorKind 是
async ,将 received 设为
Completion
(?
AsyncGeneratorYield
(?
IteratorValue
(innerResult )))。
vii. 否则,将 received 设为
Completion
(
GeneratorYield
(innerResult ))。
b. 否则,如果 received 是
throw completion
,则
i. 令 throw 为 ?
GetMethod
(iterator , "throw" )。
ii. 如果 throw 不是
undefined ,则
1. 令 innerResult 为 ?
Call
(throw , iterator , « received .[[Value]] »)。
2. 如果 generatorKind 是
async ,将 innerResult 设为 ?
Await
(innerResult )。
3. 注意:内部迭代器的 throw
方法抛出的异常会被传播。throw
方法的正常完成与 next
类似。
4. 如果 innerResult
不是对象
,抛出
TypeError 异常。
5. 令 done 为 ?
IteratorComplete
(innerResult )。
6. 如果 done 为 true ,则
1. 返回 ?
IteratorValue
(innerResult )。
7. 如果 generatorKind 是
async ,将 received 设为
Completion
(
AsyncGeneratorYield
(?
IteratorValue
(innerResult )))。
8. 否则,将 received 设为
Completion
(
GeneratorYield
(innerResult ))。
iii. 否则,
1.
断言
:received 是
return
completion
。
2. 令 return 为 ?
GetMethod
(iterator , "return" )。
3. 如果 return 是
undefined ,则
a. 将 value 设为 received .[[Value]] 。
b. 如果 generatorKind 是
async ,则
i. 将 value 设为 ?
Await
(value )。
c. 返回
Completion
Record
{ [[Type]] : return , [[Value]] : value , [[Target]] :
empty }。
4. 令 innerReturnResult 为 ?
Call
(return , iterator , « received .[[Value]] »)。
5. 如果 generatorKind 是
async ,将 innerReturnResult 设为 ?
Await
(innerReturnResult )。
6. 如果 innerReturnResult
不是对象
,抛出
TypeError 异常。
7. 令 done 为 ?
IteratorComplete
(innerReturnResult )。
8. 如果 done 为 true ,则
a. 将 value 设为 ?
IteratorValue
(innerReturnResult )。
b. 返回
Completion
Record
{ [[Type]] : return , [[Value]] : value , [[Target]] :
empty }。
9. 如果 generatorKind 是
async ,将 received 设为
Completion
(
AsyncGeneratorYield
(?
IteratorValue
(innerReturnResult )))。
10. 否则,将 received 设为
Completion
(
GeneratorYield
(innerReturnResult ))。
15.6 异步生成器函数定义
语法
AsyncGeneratorDeclaration [Yield,
Await, Default] :
async
[no LineTerminator
here]
function
*
BindingIdentifier [?Yield,
?Await]
(
FormalParameters [+Yield,
+Await]
)
{
AsyncGeneratorBody
}
[+Default]
async
[no LineTerminator
here]
function
*
(
FormalParameters [+Yield,
+Await]
)
{
AsyncGeneratorBody
}
AsyncGeneratorExpression
:
async
[no LineTerminator
here]
function
*
BindingIdentifier [+Yield,
+Await] opt
(
FormalParameters [+Yield,
+Await]
)
{
AsyncGeneratorBody
}
AsyncGeneratorMethod [Yield,
Await] :
async
[no LineTerminator
here]
*
ClassElementName [?Yield,
?Await]
(
UniqueFormalParameters [+Yield,
+Await]
)
{
AsyncGeneratorBody
}
AsyncGeneratorBody
:
FunctionBody [+Yield,
+Await]
注 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 (一个
列表
of
ECMAScript 语言值
),并返回一个
throw completion
或
return completion
。它分段定义如下:
AsyncGeneratorBody
:
FunctionBody
1. 执行 ?
FunctionDeclarationInstantiation
(functionObject , argumentsList )。
2. 令 generator 为 ?
OrdinaryCreateFromConstructor
(functionObject ,
"%AsyncGeneratorFunction.prototype.prototype%" , «
[[AsyncGeneratorState]] ,
[[AsyncGeneratorContext]] ,
[[AsyncGeneratorQueue]] ,
[[GeneratorBrand]] »)。
3. 将 generator .[[GeneratorBrand]]
设为 empty 。
4. 执行
AsyncGeneratorStart
(generator ,
FunctionBody
)。
5. 返回
Completion Record
{
[[Type]] : return ,
[[Value]] : generator ,
[[Target]] : empty }。
15.6.3 运行时语义:InstantiateAsyncGeneratorFunctionObject
语法定向操作
InstantiateAsyncGeneratorFunctionObject 接受参数 env (一个
环境记录
)和 privateEnv (一个
私有环境记录
或 null ),并返回一个 ECMAScript
函数对象
。它分段定义如下:
AsyncGeneratorDeclaration
:
async
function
*
BindingIdentifier
(
FormalParameters
)
{
AsyncGeneratorBody
}
1. 令 name 为
StringValue
of
BindingIdentifier
。
2. 令 sourceText 为
源文本匹配
AsyncGeneratorDeclaration
。
3. 令 F 为
OrdinaryFunctionCreate
(
%AsyncGeneratorFunction.prototype%
,
sourceText ,
FormalParameters
,
AsyncGeneratorBody
,
non-lexical-this , env , privateEnv )。
4. 执行
SetFunctionName
(F , name )。
5. 令 prototype 为
OrdinaryObjectCreate
(
%AsyncGeneratorFunction.prototype.prototype%
)。
6. 执行 !
DefinePropertyOrThrow
(F , "prototype" , PropertyDescriptor {
[[Value]] : prototype ,
[[Writable]] : true ,
[[Enumerable]] : false ,
[[Configurable]] : false })。
7. 返回 F 。
AsyncGeneratorDeclaration
:
async
function
*
(
FormalParameters
)
{
AsyncGeneratorBody
}
1. 令 sourceText 为
源文本匹配
AsyncGeneratorDeclaration
。
2. 令 F 为
OrdinaryFunctionCreate
(
%AsyncGeneratorFunction.prototype%
,
sourceText ,
FormalParameters
,
AsyncGeneratorBody
,
non-lexical-this , env , privateEnv )。
3. 执行
SetFunctionName
(F , "default" )。
4. 令 prototype 为
OrdinaryObjectCreate
(
%AsyncGeneratorFunction.prototype.prototype%
)。
5. 执行 !
DefinePropertyOrThrow
(F , "prototype" , PropertyDescriptor {
[[Value]] : prototype ,
[[Writable]] : true ,
[[Enumerable]] : false ,
[[Configurable]] : false })。
6. 返回 F 。
注
匿名的
AsyncGeneratorDeclaration
只能作为 export default
声明的一部分出现。
15.6.4 运行时语义:InstantiateAsyncGeneratorFunctionExpression
语法定向操作
InstantiateAsyncGeneratorFunctionExpression 接受可选参数 name (一个
属性键
或
私有名称
),并返回一个 ECMAScript
函数对象
。它分段定义如下:
AsyncGeneratorExpression
:
async
function
*
(
FormalParameters
)
{
AsyncGeneratorBody
}
1. 如果 name 不存在,则将 name 设为空字符串 "" 。
2. 令 env 为
运行执行上下文
的词法环境。
3. 令 privateEnv 为
运行执行上下文
的私有环境。
4. 令 sourceText 为
源文本匹配
AsyncGeneratorExpression
。
5. 令 closure 为
OrdinaryFunctionCreate
(
%AsyncGeneratorFunction.prototype%
,
sourceText ,
FormalParameters
,
AsyncGeneratorBody
,
non-lexical-this , env , privateEnv )。
6. 执行
SetFunctionName
(closure , name )。
7. 令 prototype 为
OrdinaryObjectCreate
(
%AsyncGeneratorFunction.prototype.prototype%
)。
8. 执行 !
DefinePropertyOrThrow
(closure , "prototype" , PropertyDescriptor {
[[Value]] : prototype ,
[[Writable]] : true ,
[[Enumerable]] : false ,
[[Configurable]] : false })。
9. 返回 closure 。
AsyncGeneratorExpression
:
async
function
*
BindingIdentifier
(
FormalParameters
)
{
AsyncGeneratorBody
}
1.
断言
: name 不存在。
2. 将 name 设为
StringValue
of
BindingIdentifier
。
3. 令 outerEnv 为
运行执行上下文
的词法环境。
4. 令 funcEnv 为
NewDeclarativeEnvironment
(outerEnv )。
5. 执行 !
funcEnv .CreateImmutableBinding(name , false )。
6. 令 privateEnv 为
运行执行上下文
的私有环境。
7. 令 sourceText 为
源文本匹配
AsyncGeneratorExpression
。
8. 令 closure 为
OrdinaryFunctionCreate
(
%AsyncGeneratorFunction.prototype%
,
sourceText ,
FormalParameters
,
AsyncGeneratorBody
,
non-lexical-this , funcEnv , privateEnv )。
9. 执行
SetFunctionName
(closure , name )。
10. 令 prototype 为
OrdinaryObjectCreate
(
%AsyncGeneratorFunction.prototype.prototype%
)。
11. 执行 !
DefinePropertyOrThrow
(closure , "prototype" , PropertyDescriptor {
[[Value]] : prototype ,
[[Writable]] : true ,
[[Enumerable]] : false ,
[[Configurable]] : false })。
12. 执行 !
funcEnv .InitializeBinding(name , closure )。
13. 返回 closure 。
注
15.6.5 运行时语义:评估
AsyncGeneratorExpression
:
async
function
*
BindingIdentifier
opt
(
FormalParameters
)
{
AsyncGeneratorBody
}
1. 返回
InstantiateAsyncGeneratorFunctionExpression
的
AsyncGeneratorExpression
。
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
1. 如果 PropName 的
MethodDefinition 是
"constructor" ,返回 constructor-method 。
2. 返回 non-constructor-method 。
ClassElement
:
static
MethodDefinition
FieldDefinition
;
static
FieldDefinition
;
1. 返回 non-constructor-method 。
ClassElement
: ClassStaticBlock
1. 返回 non-constructor-method 。
ClassElement
: ;
1. 返回 empty 。
15.7.3 静态语义:ConstructorMethod
语法导向操作
ConstructorMethod 不接受参数,并返回一个 ClassElement
解析节点 或
empty 。它在以下各个生成式上分段定义:
ClassElementList
: ClassElement
1. 如果 ClassElementKind
的 ClassElement 是
constructor-method ,返回 ClassElement 。
2. 返回 empty 。
ClassElementList
:
ClassElementList
ClassElement
1. 让 head 为 ConstructorMethod
的 ClassElementList 。
2. 如果 head 不是 empty ,返回
head 。
3. 如果 ClassElementKind
的 ClassElement 是
constructor-method ,返回 ClassElement 。
4. 返回 empty 。
注
早期错误规则确保只有一个名为
"constructor" 的方法定义,并且它不是 访问器
属性 或生成器定义。
15.7.4 静态语义:IsStatic
语法导向操作
IsStatic 不接受参数,并返回一个布尔值。它在以下各个生成式上分段定义:
ClassElement
: MethodDefinition
1. 返回 false 。
ClassElement
:
static
MethodDefinition
1. 返回 true 。
ClassElement
:
FieldDefinition
;
1. 返回 false 。
ClassElement
:
static
FieldDefinition
;
1. 返回 true 。
ClassElement
: ClassStaticBlock
1. 返回 true 。
ClassElement
: ;
1. 返回 false 。
15.7.5 静态语义:NonConstructorElements
语法导向操作
NonConstructorElements 不接受参数,并返回一个包含 ClassElement 的解析节点 的 列表 。它在以下各个生成式上分段定义:
ClassElementList
: ClassElement
1. 如果ClassElementKind
属于ClassElement 且为non-constructor-method ,则
a. 返回« ClassElement »。
2. 返回一个新的空列表 。
ClassElementList
:
ClassElementList
ClassElement
1. 让list 等于NonConstructorElements
属于ClassElementList 。
2. 如果ClassElementKind
属于ClassElement 且为non-constructor-method ,则
a. 将ClassElement 追加到list 的末尾。
3. 返回list 。
15.7.6 静态语义:PrototypePropertyNameList
语法导向操作
PrototypePropertyNameList 不接受参数,并返回一个包含属性键 的列表 。它在以下各个生成式上分段定义:
ClassElementList
: ClassElement
1. 令 propName 等于 PropName 属于
ClassElement 。
2. 如果 propName
是empty ,则返回一个新的空列表 。
3. 如果 IsStatic 属于
ClassElement
是true ,则返回一个新的空列表 。
4. 返回 « propName »。
ClassElementList
:
ClassElementList
ClassElement
1. 令 list 等于 PrototypePropertyNameList
属于ClassElementList 。
2. 令 propName 等于 PropName 属于
ClassElement 。
3. 如果 propName 是empty ,则返回
list 。
4. 如果 IsStatic 属于
ClassElement
是true ,则返回 list 。
5. 返回列表连接 list 和 «
propName »。
15.7.7 静态语义:AllPrivateIdentifiersValid
语法导向操作
AllPrivateIdentifiersValid 接受参数 names (一个字符串列表 )并返回一个布尔值。
本规范中未列出的每个语法生成式替代项隐含有以下默认的 AllPrivateIdentifiersValid 定义:
1. 对于此解析节点 的每个子节点child ,执行以下操作:
a. 如果 child 是一个非终结符的实例,那么
i. 如果 AllPrivateIdentifiersValid
属于 child 并带有参数 names 为 false ,则返回
false 。
2. 返回 true 。
MemberExpression
:
MemberExpression
.
PrivateIdentifier
1. 如果 names 包含 StringValue 属于
PrivateIdentifier ,那么
a. 返回 AllPrivateIdentifiersValid
属于 MemberExpression 并带有参数
names 。
2. 返回 false 。
CallExpression
:
CallExpression
.
PrivateIdentifier
1. 如果 names 包含 StringValue 属于
PrivateIdentifier ,那么
a. 返回 AllPrivateIdentifiersValid
属于 CallExpression 并带有参数
names 。
2. 返回 false 。
OptionalChain
:
?.
PrivateIdentifier
1. 如果 names 包含 StringValue 属于
PrivateIdentifier ,返回
true 。
2. 返回 false 。
OptionalChain
:
OptionalChain
.
PrivateIdentifier
1. 如果 names 包含 StringValue 属于
PrivateIdentifier ,那么
a. 返回 AllPrivateIdentifiersValid
属于 OptionalChain 并带有参数
names 。
2. 返回 false 。
ClassBody :
ClassElementList
1. 令 newNames 等于 列表连接
names 和 PrivateBoundIdentifiers
属于 ClassBody 。
2. 返回 AllPrivateIdentifiersValid
属于 ClassElementList 并带有参数
newNames 。
RelationalExpression
:
PrivateIdentifier
in
ShiftExpression
1. 如果 names 包含 StringValue 属于
PrivateIdentifier ,那么
a. 返回 AllPrivateIdentifiersValid
属于 ShiftExpression 并带有参数
names 。
2. 返回 false 。
15.7.8 静态语义:PrivateBoundIdentifiers
语法导向操作
PrivateBoundIdentifiers 不接受参数并返回一个字符串列表 。它通过以下生成式逐步定义:
FieldDefinition
:
ClassElementName
Initializer opt
1. 返回PrivateBoundIdentifiers
属于 ClassElementName 。
ClassElementName
: PrivateIdentifier
1. 返回一个列表 ,其唯一元素是StringValue 属于
PrivateIdentifier 。
ClassElementName
:
PropertyName
ClassElement
:
ClassStaticBlock
;
1. 返回一个新的空列表 。
ClassElementList
:
ClassElementList
ClassElement
1. 令 names1 为PrivateBoundIdentifiers
属于ClassElementList 。
2. 令 names2 为PrivateBoundIdentifiers
属于ClassElement 。
3. 返回 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
}
1. 返回PrivateBoundIdentifiers
属于 ClassElementName 。
15.7.9 静态语义:ContainsArguments
语法导向操作
ContainsArguments 不接受参数并返回一个布尔值。
本规范中未列出的每个语法生成式替代方案隐式具有以下 ContainsArguments 的默认定义:
1. 对于此解析节点 的每个子节点child ,执行以下操作
a. 如果child 是一个非终结符实例,则
i. 如果ContainsArguments
属于child 为true ,则返回true 。
2. 返回false 。
IdentifierReference
: Identifier
1. 如果StringValue 属于
Identifier
为"arguments" ,则返回true 。
2. 返回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
}
1. 返回false 。
MethodDefinition
:
ClassElementName
(
UniqueFormalParameters
)
{
FunctionBody
}
get
ClassElementName
(
)
{
FunctionBody
}
set
ClassElementName
(
PropertySetParameterList
)
{
FunctionBody
}
GeneratorMethod
:
*
ClassElementName
(
UniqueFormalParameters
)
{
GeneratorBody
}
AsyncGeneratorMethod
:
async
*
ClassElementName
(
UniqueFormalParameters
)
{
AsyncGeneratorBody
}
AsyncMethod
:
async
ClassElementName
(
UniqueFormalParameters
)
{
AsyncFunctionBody
}
1. 返回false 。
MethodDefinition
:
ClassElementName
(
UniqueFormalParameters
)
{
FunctionBody
}
get
ClassElementName
(
)
{
FunctionBody
}
set
ClassElementName
(
PropertySetParameterList
)
{
FunctionBody
}
GeneratorMethod
:
*
ClassElementName
(
UniqueFormalParameters
)
{
GeneratorBody
}
AsyncGeneratorMethod
:
async
*
ClassElementName
(
UniqueFormalParameters
)
{
AsyncGeneratorBody
}
AsyncMethod
:
async
ClassElementName
(
UniqueFormalParameters
)
{
AsyncFunctionBody
}
1. 返回ContainsArguments
属于ClassElementName 。
15.7.10 运行时语义: ClassFieldDefinitionEvaluation
ClassFieldDefinitionEvaluation
语法直接操作接收参数 homeObject (一个对象),并返回一个包含 ClassFieldDefinition
Record 的正常完成记录或一个 异常完成记录 。它根据以下语法规则逐一定义:
FieldDefinition
:
ClassElementName
Initializer opt
1. 令 name 为 ? Evaluation
ClassElementName 。
2. 如果 Initializer 存在,那么:
a. 令 formalParameterList 为 FormalParameters : [empty] 的一个实例。
b. 令 env 为 运行执行上下文 的词法环境。
c. 令 privateEnv 为 运行执行上下文 的私有环境。
d. 令 sourceText 为 Unicode 代码点的空序列。
e. 令 initializer 为 OrdinaryFunctionCreate (%Function.prototype% ,
sourceText , formalParameterList , Initializer ,
non-lexical-this , env , privateEnv )。
f. 执行 MakeMethod (initializer ,
homeObject )。
g. 设置 initializer .[[ClassFieldInitializerName]] 为 name 。
3. 否则:
a. 令 initializer 为 empty 。
4. 返回 ClassFieldDefinition
Record { [[Name]] : name , [[Initializer]] : initializer }。
注
为 initializer 创建的函数永远不会直接被 ECMAScript 代码访问。
15.7.11 运行时语义:ClassStaticBlockDefinitionEvaluation
ClassStaticBlockDefinitionEvaluation
语法直接操作接收参数 homeObject (一个对象),并返回一个 ClassStaticBlockDefinition
Record 。它根据以下语法规则逐一定义:
ClassStaticBlock
:
static
{
ClassStaticBlockBody
}
1. 令 lex 为 运行执行上下文
的词法环境。
2. 令 privateEnv 为 运行执行上下文
的私有环境。
3. 令 sourceText 为 Unicode 代码点的空序列。
4. 令 formalParameters 为 FormalParameters : [empty] 的一个实例。
5. 令 bodyFunction 为 OrdinaryFunctionCreate (%Function.prototype% ,
sourceText , formalParameters , ClassStaticBlockBody ,
non-lexical-this , lex , privateEnv )。
6. 执行 MakeMethod (bodyFunction ,
homeObject )。
7. 返回 ClassStaticBlockDefinition
Record { [[BodyFunction]] : bodyFunction }。
注
bodyFunction 创建的函数永远不会直接被 ECMAScript 代码访问。
15.7.12 运行时语义:EvaluateClassStaticBlockBody
EvaluateClassStaticBlockBody
语法直接操作接收参数 functionObject (一个 ECMAScript 函数对象 ),并返回一个 正常完成记录 ,包含一个
ECMAScript 语言值 ,或一个
中断完成 。它根据以下语法规则逐一定义:
ClassStaticBlockBody
:
ClassStaticBlockStatementList
1. 断言 :functionObject 是由 ClassStaticBlockDefinitionEvaluation
第 5 步创建的合成函数。
2. 执行 ! FunctionDeclarationInstantiation (functionObject ,
« »)。
3. 返回 ? Evaluation of
ClassStaticBlockStatementList 。
15.7.13 运行时语义:ClassElementEvaluation
语法直接操作
ClassElementEvaluation 接受参数 object (一个对象)并返回一个包含
正常完成
的
ClassFieldDefinition
记录
、
ClassStaticBlockDefinition
记录
、
PrivateElement
或
unused ,或返回一个
中止完成
。其分段定义如下生产:
ClassElement
:
FieldDefinition
;
static
FieldDefinition
;
1. 返回 ?
ClassFieldDefinitionEvaluation
的
FieldDefinition
参数为 object 。
ClassElement
:
MethodDefinition
static
MethodDefinition
1. 返回 ?
MethodDefinitionEvaluation
的
MethodDefinition
参数为 object 和 false 。
ClassElement
:
ClassStaticBlock
1. 返回
ClassStaticBlockDefinitionEvaluation
的
ClassStaticBlock
参数为 object 。
ClassElement
:
;
1. 返回 unused 。
15.7.14 运行时语义:ClassDefinitionEvaluation
语法直接操作
ClassDefinitionEvaluation 接受参数 classBinding (字符串或undefined )和
className (
属性键
或
私有名称
),并返回一个包含
正常完成
的
函数对象
或
中止完成
。
注
为了方便规范,私有方法和访问器与私有字段一起包含在类实例的 [[PrivateElements]]
插槽中。然而,任何给定对象都具有某个类定义的所有或无任何私有方法和访问器。此功能的设计使得实现可以选择使用不需要单独跟踪每个方法或访问器的策略来实现私有方法和访问器。
例如,实现可以直接将实例私有方法与相应的
私有名称
相关联,并跟踪每个对象,哪些类
构造函数
已经使用该对象作为它们的 this
值运行。然后在对象上查找实例私有方法的过程是检查定义该方法的类
构造函数
是否已用于初始化该对象,然后返回与
私有名称
相关的方法。
这与私有字段不同:因为字段初始化程序在类实例化期间可能会抛出异常,个别对象可能具有给定类的某些私有字段的子集,因此一般需要单独跟踪私有字段。
其分段定义如下生产:
ClassTail
:
ClassHeritage
opt
{
ClassBody
opt
}
1. 令 env 为
运行执行上下文
的 LexicalEnvironment。
2. 令 classEnv 为
NewDeclarativeEnvironment
(env )。
3. 如果 classBinding 不是 undefined ,则
a. 执行
! classEnv .CreateImmutableBinding(classBinding , true )。
4. 令 outerPrivateEnvironment 为
运行执行上下文
的 PrivateEnvironment。
5. 令 classPrivateEnvironment 为
NewPrivateEnvironment
(outerPrivateEnvironment )。
6. 如果
ClassBody
存在,则
a. 对于
PrivateBoundIdentifiers
的每个字符串 dn ,都
i. 如果 classPrivateEnvironment .[[Names]] 包含一个
私有名称
pn ,且 pn .[[Description]] 为 dn ,则
1.
断言
:这仅对 getter/setter 对可能。
ii. 否则,
1. 令 name 为新的
私有名称
,其 [[Description]] 为 dn 。
2. 将 name 添加到
classPrivateEnvironment .[[Names]] 。
7. 如果
ClassHeritage
不存在,则
a. 令 protoParent 为
%Object.prototype%
。
b. 令 constructorParent 为
%Function.prototype%
。
8. 否则,
a. 将
运行执行上下文
的 LexicalEnvironment 设置为 classEnv 。
b. 注意:在评估
ClassHeritage
时,
运行执行上下文
的 PrivateEnvironment 是 outerPrivateEnvironment 。
c. 令 superclassRef 为
Completion
(
Evaluation
的
ClassHeritage
)。
d. 将
运行执行上下文
的 LexicalEnvironment 设置为 env 。
e. 令 superclass 为 ?
GetValue
(? superclassRef )。
f. 如果 superclass 是 null ,则
i. 令 protoParent 为 null 。
ii. 令 constructorParent 为
%Function.prototype%
。
g. 否则如果
IsConstructor
(superclass ) 是 false ,则
i. 抛出一个 TypeError 异常。
h. 否则,
i. 令 protoParent 为 ?
Get
(superclass , "prototype" )。
ii. 如果 protoParent
不是一个对象
且 protoParent 不是 null ,则抛出一个
TypeError 异常。
iii. 令 constructorParent 为 superclass 。
9. 令 proto 为
OrdinaryObjectCreate
(protoParent )。
10. 如果
ClassBody
不存在,令 constructor 为 empty 。
11. 否则,令 constructor 为
ConstructorMethod
的
ClassBody
。
12. 将
运行执行上下文
的 LexicalEnvironment 设置为 classEnv 。
13. 将
运行执行上下文
的 PrivateEnvironment 设置为 classPrivateEnvironment 。
14. 如果 constructor 是 empty ,则
a. 令 defaultConstructor 为一个新的
抽象闭包
,它没有参数且不捕获任何内容,当被调用时执行以下步骤:
i. 令 args 为传递给此函数的由 [[Call]] 或 [[Construct]] 传递的参数列表。
ii. 如果 NewTarget 是 undefined ,则抛出一个
TypeError 异常。
iii. 令 F 为
活动函数对象
。
iv. 如果 F .[[ConstructorKind]] 是 derived ,则
1. 注意:此分支的行为类似于
constructor(...args) { super(...args); }
。最显著的区别在于,虽然前述的
ECMAScript 源代码
可观察到调用 %Array.prototype%
上的
@@iterator
方法,但此函数不会。
2. 令 func 为 ! F .[[GetPrototypeOf]] ()。
3. 如果
IsConstructor
(func ) 是 false ,则抛出一个 TypeError
异常。
4. 令 result 为 ?
Construct
(func , args , NewTarget)。
v. 否则,
1. 注意:此分支的行为类似于 constructor() {}
。
2. 令 result 为 ?
OrdinaryCreateFromConstructor
(NewTarget, "%Object.prototype%" )。
vi. 执行 ?
InitializeInstanceElements
(result , F )。
vii. 返回 result 。
b. 令 F 为
CreateBuiltinFunction
(defaultConstructor , 0, className , « [[ConstructorKind]] , [[SourceText]] »,
当前 Realm 记录
, constructorParent )。
15. 否则,
a. 令 constructorInfo 为 !
DefineMethod
(constructor ,带参数 proto 和 constructorParent )。
b. 令 F 为 constructorInfo .[[Closure]] 。
c. 执行
MakeClassConstructor
(F )。
d. 执行
SetFunctionName
(F , className )。
16. 执行
MakeConstructor
(F , false , proto )。
17. 如果
ClassHeritage
存在,设置 F .[[ConstructorKind]] 为
derived 。
18. 执行 !
DefineMethodProperty
(proto , "constructor" , F , false )。
19. 如果
ClassBody
不存在,令 elements 为一个新的空的
列表
。
20. 否则,令 elements 为
NonConstructorElements
的
ClassBody
。
21. 令 instancePrivateMethods 为一个新的空的
列表
。
22. 令 staticPrivateMethods 为一个新的空的
列表
。
23. 令 instanceFields 为一个新的空的
列表
。
24. 令 staticElements 为一个新的空的
列表
。
25. 对于 elements 的每个
ClassElement
e ,执行
a. 如果
IsStatic
的 e 是 false ,则
i. 令 element 为
Completion
(
ClassElementEvaluation
的 e 带参数 proto )。
b. 否则,
i. 令 element 为
Completion
(
ClassElementEvaluation
的 e 带参数 F )。
c. 如果 element 是一个
中止完成
,则
i. 将
运行执行上下文
的 LexicalEnvironment 设置为 env 。
ii. 将
运行执行上下文
的 PrivateEnvironment 设置为 outerPrivateEnvironment 。
iii. 返回 ? element 。
d. 设置 element 为 ! element 。
e. 如果 element 是一个
PrivateElement
,则
i.
断言
:element .[[Kind]] 不是
method 或 accessor 。
ii. 如果
IsStatic
的 e 是 false ,令 container 为
instancePrivateMethods 。
iii. 否则,令 container 为
staticPrivateMethods 。
iv. 如果 container 包含一个
PrivateElement
pe ,且 pe .[[Key]] 是
element .[[Key]] ,则
1.
断言
:element .[[Kind]] 和 pe .[[Kind]] 均为 accessor 。
2. 如果 element .[[Get]]
是 undefined ,则
a. 令 combined 为
PrivateElement
{ [[Key]] : element .[[Key]] , [[Kind]] :
accessor , [[Get]] : pe .[[Get]] , [[Set]] : element .[[Set]] }。
3. 否则,
a. 令 combined 为
PrivateElement
{ [[Key]] : element .[[Key]] , [[Kind]] :
accessor , [[Get]] :
element .[[Get]] , [[Set]] :
pe .[[Set]] }。
4. 用 combined 替换 container 中的
pe 。
v. 否则,
1. 将 element 添加到 container 。
f. 否则如果 element 是一个
ClassFieldDefinition
记录
,则
i. 如果
IsStatic
的 e 是 false ,将 element 添加到
instanceFields 。
ii. 否则,将 element 添加到 staticElements 。
g. 否则如果 element 是一个
ClassStaticBlockDefinition
记录
,则
i. 将 element 添加到 staticElements 。
26. 将
运行执行上下文
的 LexicalEnvironment 设置为 env 。
27. 如果 classBinding 不是 undefined ,则
a. 执行
! classEnv .InitializeBinding(classBinding , F )。
28. 设置 F .[[PrivateMethods]] 为
instancePrivateMethods 。
29. 设置 F .[[Fields]] 为
instanceFields 。
30. 对于 staticPrivateMethods 的每个
PrivateElement
method ,执行
a. 执行 !
PrivateMethodOrAccessorAdd
(F , method )。
31. 对于 staticElements 的每个 elementRecord ,执行
a. 如果 elementRecord 是一个
ClassFieldDefinition
记录
,则
i. 令 result 为
Completion
(
DefineField
(F , elementRecord ))。
b. 否则,
i.
断言
:elementRecord 是一个
ClassStaticBlockDefinition
记录
。
ii. 令 result 为
Completion
(
Call
(elementRecord .[[BodyFunction]] , F ))。
c. 如果 result 是一个
中止完成
,则
i. 将
运行执行上下文
的 PrivateEnvironment 设置为 outerPrivateEnvironment 。
ii. 返回 ? result 。
32. 将
运行执行上下文
的 PrivateEnvironment 设置为 outerPrivateEnvironment 。
33. 返回 F 。
15.7.15 Runtime语义: BindingClassDeclarationEvaluation
语法指向操作
BindingClassDeclarationEvaluation 不接受参数,并返回
包含
函数对象
的正常完成或
突然完成
。它分块定义如下:
ClassDeclaration
:
class
BindingIdentifier
ClassTail
1. 让 className 为
StringValue
of
BindingIdentifier
。
2. 让 value 为 ?
ClassDefinitionEvaluation
of
ClassTail
with arguments
className 和 className 。
3. 将 value .[[SourceText]] 设置为
由
ClassDeclaration
匹配的源代码文本。
4. 让 env 为
运行执行上下文
的词法环境。
5. 执行 ?
InitializeBoundName
(className , value , env )。
6. 返回 value 。
ClassDeclaration
:
class
ClassTail
1. 让 value 为 ?
ClassDefinitionEvaluation
of
ClassTail
with arguments
undefined 和 "default" 。
2. 将 value .[[SourceText]] 设置为
由
ClassDeclaration
匹配的源代码文本。
3. 返回 value 。
注
ClassDeclaration
:
class
ClassTail
仅在作为
ExportDeclaration
的一部分时出现,并且其绑定的建立在该生成的评估操作中处理。详见
16.2.3.7
。
15.7.16 Runtime语义: Evaluation
ClassDeclaration
:
class
BindingIdentifier
ClassTail
1. 执行 ?
BindingClassDeclarationEvaluation
of this
ClassDeclaration
。
2. 返回 empty 。
注
ClassExpression
:
class
ClassTail
1. 让 value 为 ?
ClassDefinitionEvaluation
of
ClassTail
with arguments undefined 和 "" 。
2. 将 value .[[SourceText]] 设置为
由
ClassExpression
匹配的源代码文本。
3. 返回 value 。
ClassExpression
:
class
BindingIdentifier
ClassTail
1. 让 className 为
StringValue
of
BindingIdentifier
。
2. 让 value 为 ?
ClassDefinitionEvaluation
of
ClassTail
with arguments className 和 className 。
3. 将 value .[[SourceText]] 设置为
由
ClassExpression
匹配的源代码文本。
4. 返回 value 。
ClassElementName
:
PrivateIdentifier
1. 让 privateIdentifier 为
StringValue
of
PrivateIdentifier
。
2. 让 privateEnvRec 为
running execution context
的 PrivateEnvironment。
3. 让 names 为 privateEnvRec .[[Names]] 。
4.
断言
:
names 中正好有一个元素是
Private Name
,其 [[Description]] 为 privateIdentifier 。
5. 让 privateName 为
Private Name
中的 names ,其 [[Description]] 为 privateIdentifier 。
6. 返回 privateName 。
ClassStaticBlockStatementList
:
[empty]
1. 返回 undefined 。
15.8 异步函数定义
语法
AsyncFunctionDeclaration
[Yield, Await, Default]
:
async
[no
LineTerminator
here]
function
BindingIdentifier
[?Yield, ?Await]
(
FormalParameters
[~Yield, +Await]
)
{
AsyncFunctionBody
}
[+Default]
async
[no
LineTerminator
here]
function
(
FormalParameters
[~Yield, +Await]
)
{
AsyncFunctionBody
}
AsyncFunctionExpression
:
async
[no
LineTerminator
here]
function
BindingIdentifier
[~Yield, +Await]
opt
(
FormalParameters
[~Yield, +Await]
)
{
AsyncFunctionBody
}
AsyncMethod
[Yield, Await]
:
async
[no
LineTerminator
here]
ClassElementName
[?Yield, ?Await]
(
UniqueFormalParameters
[~Yield, +Await]
)
{
AsyncFunctionBody
}
AsyncFunctionBody
:
FunctionBody
[~Yield, +Await]
AwaitExpression
[Yield]
:
await
UnaryExpression
[?Yield, +Await]
注 1
当 [Await] 参数存在时,await
作为
关键字
解析为
AwaitExpression
。[Await] 参数在以下上下文的顶层存在,尽管根据非终结符的不同,参数可能在某些上下文中不存在,例如
FunctionBody
:
当
脚本
是语法
目标符号
时,当 [Await] 参数不存在时,await
可以作为标识符解析。这包括以下上下文:
注 2
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 接受参数 env (
环境记录
)和 privateEnv (
PrivateEnvironment 记录
或 null ),并返回 ECMAScript
函数对象
。它按以下生成式逐步定义:
AsyncFunctionDeclaration
:
async
function
BindingIdentifier
(
FormalParameters
)
{
AsyncFunctionBody
}
令 name 为
StringValue
的
BindingIdentifier
。
令 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 接受可选参数 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 设置为
StringValue
的
BindingIdentifier
。
令 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 接受参数 functionObject (ECMAScript
函数对象
)和 argumentsList (
列表
的
ECMAScript 语言值
),并返回
返回完成
。它按以下生成式逐步定义:
AsyncFunctionBody
:
FunctionBody
令 promiseCapability 为 !
NewPromiseCapability
(
%Promise%
)。
令 declResult 为
Completion
(
FunctionDeclarationInstantiation
(functionObject , argumentsList ))。
如果 declResult 是
突然完成
,则
执行 !
Call
(promiseCapability .[[Reject]] ,
undefined , «declResult .[[Value]] »)。
否则,
执行
AsyncFunctionStart
(promiseCapability ,
FunctionBody
)。
返回
完成记录
{ [[Type]] : return , [[Value]] : promiseCapability .[[Promise]] , [[Target]] : empty }。
15.8.5 运行时语义:评估
AsyncFunctionExpression
:
async
function
BindingIdentifier
opt
(
FormalParameters
)
{
AsyncFunctionBody
}
返回
InstantiateAsyncFunctionExpression
的
AsyncFunctionExpression
。
AwaitExpression
:
await
UnaryExpression
令 exprRef 为 ?
Evaluation
的
UnaryExpression
。
令 value 为 ?
GetValue
(exprRef )。
返回 ?
Await
(value )。
15.9 Async Arrow Function 定义
语法
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 不接受任何参数,并返回一个布尔值。它在以下生成式上逐步定义:
AsyncConciseBody
:
ExpressionBody
1. 返回 false 。
AsyncConciseBody
:
{
AsyncFunctionBody
}
1. 返回
FunctionBodyContainsUseStrict
的
AsyncFunctionBody
。
15.9.3 运行时语义:EvaluateAsyncConciseBody
语法导向操作
EvaluateAsyncConciseBody 接受参数 functionObject (一个 ECMAScript
函数对象
)和 argumentsList (一个
列表
的
ECMAScript 语言值
),并返回一个
返回完成记录
。它在以下生成式上逐步定义:
AsyncConciseBody
:
ExpressionBody
1. 让 promiseCapability 为 !
NewPromiseCapability
(
%Promise%
)。
2. 让 declResult 为
Completion
(
FunctionDeclarationInstantiation
(functionObject , argumentsList ))。
3. 如果 declResult 是一个
突然完成
,则
a. 执行 !
Call
(promiseCapability .[[Reject]] ,undefined ,« declResult .[[Value]] »)。
4. 否则,
a. 执行
AsyncFunctionStart
(promiseCapability ,
ExpressionBody
)。
5. 返回
完成记录
{ [[Type]] : return ,[[Value]] : promiseCapability .[[Promise]] ,[[Target]] : empty }。
15.9.4 运行时语义:InstantiateAsyncArrowFunctionExpression
语法导向操作
InstantiateAsyncArrowFunctionExpression 接受可选参数 name (一个
属性键
或
私有名称
),并返回一个 ECMAScript
函数对象
。它在以下生成式上逐步定义:
AsyncArrowFunction
:
async
AsyncArrowBindingIdentifier
=>
AsyncConciseBody
1. 如果 name 不存在,将 name 设置为
"" 。
2. 让 env 为
运行执行上下文
的 LexicalEnvironment。
3. 让 privateEnv 为
运行执行上下文
的 PrivateEnvironment。
4. 让 sourceText 为
匹配的源文本
AsyncArrowFunction
。
5. 让 parameters 为
AsyncArrowBindingIdentifier
。
6. 让 closure 为
OrdinaryFunctionCreate
(
%AsyncFunction.prototype%
, sourceText , parameters ,
AsyncConciseBody
, lexical-this , env , privateEnv )。
7. 执行
SetFunctionName
(closure , name )。
8. 返回 closure 。
AsyncArrowFunction
:
CoverCallExpressionAndAsyncArrowHead
=>
AsyncConciseBody
1. 如果 name 不存在,将 name 设置为
"" 。
2. 让 env 为
运行执行上下文
的 LexicalEnvironment。
3. 让 privateEnv 为
运行执行上下文
的 PrivateEnvironment。
4. 让 sourceText 为
匹配的源文本
AsyncArrowFunction
。
5. 让 head 为
AsyncArrowHead
是
覆盖的
CoverCallExpressionAndAsyncArrowHead
。
6. 让 parameters 为
ArrowFormalParameters
的 head 。
7. 让 closure 为
OrdinaryFunctionCreate
(
%AsyncFunction.prototype%
, sourceText , parameters ,
AsyncConciseBody
, lexical-this , env , privateEnv )。
8. 执行
SetFunctionName
(closure , name )。
9. 返回 closure 。
15.9.5 运行时语义:评估
AsyncArrowFunction
:
async
AsyncArrowBindingIdentifier
=>
AsyncConciseBody
CoverCallExpressionAndAsyncArrowHead
=>
AsyncConciseBody
1. 返回
InstantiateAsyncArrowFunctionExpression
的
AsyncArrowFunction
。
15.10 尾调用
15.10.1 静态语义:IsInTailPosition ( call )
抽象操作 IsInTailPosition 接受参数 call (一个 CallExpression 解析节点 ,一个 MemberExpression 解析节点 ,或者一个 OptionalChain
解析节点 ),并返回一个布尔值。它在调用时执行以下步骤:
1. 如果 源文本匹配
call 是 非严格模式代码 ,返回 false 。
2. 如果 call 不包含在 FunctionBody 、ConciseBody 或
AsyncConciseBody 中,返回
false 。
3. 让 body 为最紧密包含 call 的 FunctionBody 、ConciseBody 或
AsyncConciseBody 。
4. 如果 body 是 FunctionBody 的 GeneratorBody ,返回
false 。
5. 如果 body 是 FunctionBody 的 AsyncFunctionBody ,返回
false 。
6. 如果 body 是 FunctionBody 的 AsyncGeneratorBody ,返回
false 。
7. 如果 body 是 AsyncConciseBody ,返回
false 。
8. 返回 HasCallInTailPosition
在 body 上的结果,参数为 call 。
注
尾调用仅在 严格模式代码 中定义,因为有一个常见的非标准语言扩展(见
10.2.4 )使得可以观察到调用链上下文。
15.10.2 静态语义:HasCallInTailPosition
语法导向操作
HasCallInTailPosition 接受参数 call (一个 CallExpression 解析节点 ,一个 MemberExpression 解析节点 ,或者一个 OptionalChain
解析节点 ),并返回一个布尔值。
注 1
call 是一个 解析节点 ,表示源文本的特定范围。当以下算法将
call 与另一个 解析节点
进行比较时,实际上是在测试它们是否表示相同的源文本。
注 2
紧接在 GetValue 操作的潜在尾调用也是可能的尾调用。函数调用不能返回
引用记录 ,因此这样的
GetValue 操作将始终返回与实际函数调用结果相同的值。
它的定义依赖于以下几种产生式:
StatementList
:
StatementList
StatementListItem
1. 令 has 为 HasCallInTailPosition
对于 StatementList 的结果,参数为
call 。
2. 如果 has 为 true ,则返回
true 。
3. 返回 HasCallInTailPosition
对于 StatementListItem 的结果,参数为
call 。
FunctionStatementList
:
[empty]
StatementListItem
:
Declaration
Statement :
VariableStatement
EmptyStatement
ExpressionStatement
ContinueStatement
BreakStatement
ThrowStatement
DebuggerStatement
Block :
{
}
ReturnStatement
:
return
;
LabelledItem
:
FunctionDeclaration
ForInOfStatement
:
for
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
for
(
var
ForBinding
of
AssignmentExpression
)
Statement
for
(
ForDeclaration
of
AssignmentExpression
)
Statement
CaseBlock :
{
}
1. 返回 false 。
IfStatement
:
if
(
Expression
)
Statement
else
Statement
1. 让 has 为第一个 Statement 的 HasCallInTailPosition
的结果,参数为 call 。
2. 如果 has 为 true ,返回
true 。
3. 返回第二个 Statement 的 HasCallInTailPosition
的结果,参数为 call 。
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
1. 返回第一个 Statement 的 HasCallInTailPosition
的结果,参数为 call 。
LabelledStatement
:
LabelIdentifier
:
LabelledItem
1. 返回第一个 LabelledItem 的 HasCallInTailPosition
的结果,参数为 call 。
ReturnStatement
:
return
Expression
;
1. 返回第一个 Expression 的 HasCallInTailPosition
的结果,参数为 call 。
SwitchStatement
:
switch
(
Expression
)
CaseBlock
1. 返回 HasCallInTailPosition
对 CaseBlock
的结果,参数为 call 。
CaseBlock :
{
CaseClauses opt
DefaultClause
CaseClauses opt
}
1. 让 has 为 false 。
2. 如果存在第一个 CaseClauses ,则将 has 设为
HasCallInTailPosition
对第一个 CaseClauses 的结果,参数为 call 。
3. 如果 has 为 true ,则返回
true 。
4. 将 has 设为 HasCallInTailPosition
对 DefaultClause 的结果,参数为
call 。
5. 如果 has 为 true ,则返回
true 。
6. 如果存在第二个 CaseClauses ,则将 has 设为
HasCallInTailPosition
对第二个 CaseClauses 的结果,参数为 call 。
7. 返回 has 。
CaseClauses
:
CaseClauses
CaseClause
1. 让 has 为 HasCallInTailPosition
对 CaseClauses
的结果,参数为 call 。
2. 如果 has 为 true ,则返回
true 。
3. 返回 HasCallInTailPosition
对 CaseClause
的结果,参数为 call 。
CaseClause
:
case
Expression
:
StatementList opt
DefaultClause
:
default
:
StatementList opt
1. 如果存在 StatementList ,则返回 HasCallInTailPosition
对 StatementList 的结果,参数为
call 。
2. 返回 false 。
TryStatement
:
try
Block
Catch
1. 返回 HasCallInTailPosition
对 Catch 的结果,参数为
call 。
TryStatement
:
try
Block
Finally
try
Block
Catch
Finally
1. 返回 HasCallInTailPosition
对 Finally 的结果,参数为
call 。
Catch :
catch
(
CatchParameter
)
Block
1. 返回 HasCallInTailPosition
对 Block 的结果,参数为
call 。
AssignmentExpression
:
YieldExpression
ArrowFunction
AsyncArrowFunction
LeftHandSideExpression
=
AssignmentExpression
LeftHandSideExpression
AssignmentOperator
AssignmentExpression
LeftHandSideExpression
&&=
AssignmentExpression
LeftHandSideExpression
||=
AssignmentExpression
LeftHandSideExpression
??=
AssignmentExpression
BitwiseANDExpression
:
BitwiseANDExpression
&
EqualityExpression
BitwiseXORExpression
:
BitwiseXORExpression
^
BitwiseANDExpression
BitwiseORExpression
:
BitwiseORExpression
|
BitwiseXORExpression
EqualityExpression
:
EqualityExpression
==
RelationalExpression
EqualityExpression
!=
RelationalExpression
EqualityExpression
===
RelationalExpression
EqualityExpression
!==
RelationalExpression
RelationalExpression
:
RelationalExpression
<
ShiftExpression
RelationalExpression
>
ShiftExpression
RelationalExpression
<=
ShiftExpression
RelationalExpression
>=
ShiftExpression
RelationalExpression
instanceof
ShiftExpression
RelationalExpression
in
ShiftExpression
PrivateIdentifier
in
ShiftExpression
ShiftExpression
:
ShiftExpression
<<
AdditiveExpression
ShiftExpression
>>
AdditiveExpression
ShiftExpression
>>>
AdditiveExpression
AdditiveExpression
:
AdditiveExpression
+
MultiplicativeExpression
AdditiveExpression
-
MultiplicativeExpression
MultiplicativeExpression
:
MultiplicativeExpression
MultiplicativeOperator
ExponentiationExpression
ExponentiationExpression
:
UpdateExpression
**
ExponentiationExpression
UpdateExpression
:
LeftHandSideExpression
++
LeftHandSideExpression
--
++
UnaryExpression
--
UnaryExpression
UnaryExpression
:
delete
UnaryExpression
void
UnaryExpression
typeof
UnaryExpression
+
UnaryExpression
-
UnaryExpression
~
UnaryExpression
!
UnaryExpression
AwaitExpression
CallExpression
:
SuperCall
ImportCall
CallExpression
[
Expression
]
CallExpression
.
IdentifierName
CallExpression
.
PrivateIdentifier
NewExpression
:
new
NewExpression
MemberExpression
:
MemberExpression
[
Expression
]
MemberExpression
.
IdentifierName
SuperProperty
MetaProperty
new
MemberExpression
Arguments
MemberExpression
.
PrivateIdentifier
PrimaryExpression
:
this
IdentifierReference
Literal
ArrayLiteral
ObjectLiteral
FunctionExpression
ClassExpression
GeneratorExpression
AsyncFunctionExpression
AsyncGeneratorExpression
RegularExpressionLiteral
TemplateLiteral
1. 返回 false 。
Expression
:
AssignmentExpression
Expression
,
AssignmentExpression
1. 返回 HasCallInTailPosition
对 AssignmentExpression
的调用,参数为 call 。
ConditionalExpression
:
ShortCircuitExpression
?
AssignmentExpression
:
AssignmentExpression
1. 让 has 为第一个 AssignmentExpression 的
HasCallInTailPosition
调用,参数为 call 。
2. 如果 has 为 true ,返回
true 。
3. 返回第二个 AssignmentExpression 的
HasCallInTailPosition
调用,参数为 call 。
LogicalANDExpression
:
LogicalANDExpression
&&
BitwiseORExpression
1. 返回 HasCallInTailPosition
对 BitwiseORExpression 的
调用,参数为 call 。
LogicalORExpression
:
LogicalORExpression
||
LogicalANDExpression
1. 返回 HasCallInTailPosition
对 LogicalANDExpression 的
调用,参数为 call 。
CoalesceExpression
:
CoalesceExpressionHead
??
BitwiseORExpression
1. 返回 HasCallInTailPosition
对 BitwiseORExpression 的
调用,参数为 call 。
CallExpression
:
CoverCallExpressionAndAsyncArrowHead
CallExpression
Arguments
CallExpression
TemplateLiteral
1. 如果此 CallExpression 是
call ,则返回 true 。
2. 返回 false 。
OptionalExpression
:
MemberExpression
OptionalChain
CallExpression
OptionalChain
OptionalExpression
OptionalChain
1. 返回 HasCallInTailPosition
对 OptionalChain 的结果,参数为
call 。
OptionalChain
:
?.
[
Expression
]
?.
IdentifierName
?.
PrivateIdentifier
OptionalChain
[
Expression
]
OptionalChain
.
IdentifierName
OptionalChain
.
PrivateIdentifier
1. 返回 false 。
OptionalChain
:
?.
Arguments
OptionalChain
Arguments
1. 如果这个 OptionalChain 是 call ,则返回
true 。
2. 返回 false 。
MemberExpression
:
MemberExpression
TemplateLiteral
1. 如果这个 MemberExpression 是
call ,则返回 true 。
2. 返回 false 。
PrimaryExpression
: CoverParenthesizedExpressionAndArrowParameterList
1. 令 expr 为由 ParenthesizedExpression
表示的表达式,该表达式由 覆盖 ,由 CoverParenthesizedExpressionAndArrowParameterList
包含。
2. 返回 HasCallInTailPosition
对 expr 和参数 call 的结果。
ParenthesizedExpression
:
(
Expression
)
1. 返回 HasCallInTailPosition
对 Expression
和参数 call 的结果。
15.10.3 PrepareForTailCall ( )
抽象操作 PrepareForTailCall 不接受任何参数,并返回 unused 。调用时执行以下步骤:
1. 断言 :当前的 执行上下文 不会随后用于任何 ECMAScript
代码或内置函数的评估。在调用此抽象操作之后,调用 Call 将创建并推送一个新的 执行上下文 ,然后再执行任何这样的评估。
2. 丢弃与当前的 执行上下文 相关的所有资源。
3. 返回 unused 。
尾位置调用必须在调用目标函数之前释放当前执行函数的任何瞬态内部资源 执行上下文 ,或者重新利用这些资源来支持目标函数。
注
例如,尾位置调用应该仅在目标函数的激活记录的大小超出调用函数的激活记录大小时,才增加实现的激活记录栈的大小。如果目标函数的激活记录更小,则栈的总大小应减少。
16 ECMAScript 语言:脚本和模块
16.1 脚本
语法
Script :
ScriptBody opt
ScriptBody :
StatementList [~Yield,
~Await, ~Return]
16.1.1 静态语义:早期错误
Script :
ScriptBody
ScriptBody
: StatementList
16.1.2 静态语义:IsStrict
语法导向操作 syntax-directed
operation IsStrict 不接受任何参数,并返回一个布尔值。它在以下产生式上逐步定义:
Script :
ScriptBody opt
1. 如果 ScriptBody 存在且 Directive Prologue 中包含 Use Strict Directive ,则返回
true ;否则,返回 false 。
16.1.3 运行时语义:评估
Script :
[空]
1. 返回 undefined 。
16.1.4 脚本记录
脚本记录 封装了有关正在评估的脚本的信息。每个脚本记录包含了
表 40 中列出的字段。
表 40: 脚本记录 字段
字段名称
值类型
含义
[[Realm]]
一个 Realm 记录 或
undefined
此脚本创建时所在的 realm 。如果尚未分配,则为
undefined 。
[[ECMAScriptCode]]
一个 脚本
解析节点
解析此脚本的源文本后的结果。
[[LoadedModules]]
一个 列表 ,其中包含
记录 ,字段包括
[[Specifier]] (字符串)和 [[Module]] (模块记录 )
从此脚本导入的规范符字符串到解析的 模块记录
的映射。列表中不会包含两个具有相同 [[Specifier]] 的不同 记录 。
[[HostDefined]]
任何东西(默认值为 empty )
供 宿主环境 使用的字段,用于与脚本关联附加信息。
16.1.5 解析脚本 ( sourceText , realm , hostDefined
)
抽象操作 ParseScript 接受以下参数:sourceText (ECMAScript 源文本 )、realm (一个
Realm
记录 或 undefined )、以及 hostDefined (任何值),并返回一个 脚本记录
或一个非空的 列表 的
SyntaxError 对象。它基于将 sourceText 解析为 脚本 的结果创建一个 脚本记录 。调用时,它执行以下步骤:
1. 将 script 设为 ParseText (sourceText ,
脚本 )。
2. 如果 script 是一个错误的 列表 ,则返回
script 。
3. 返回 脚本记录 { [[Realm]] : realm , [[ECMAScriptCode]] :
script , [[LoadedModules]] : « », [[HostDefined]] : hostDefined }。
注
实现可以在对脚本源文本进行 ParseScript 之前解析脚本源文本并分析其早期错误条件。然而,任何错误的报告必须推迟到本规范实际对该源文本执行 ParseScript 的时候。
16.1.6 脚本评估 ( scriptRecord )
抽象操作 ScriptEvaluation 接受一个参数 scriptRecord (一个 脚本记录 ),并返回一个 正常完成 ,其中包含一个
ECMAScript 语言值 ,或者一个
突然完成 。调用时,它执行以下步骤:
1. 将 globalEnv 设为 scriptRecord .[[Realm]] .[[GlobalEnv]] 。
2. 将 scriptContext 设为一个新的 ECMAScript
代码执行上下文 。
3. 将 scriptContext 的 Function 设为 null 。
4. 将 Realm 设为 scriptContext 的 [[Realm]] 。
5. 将 scriptContext 的 ScriptOrModule 设为
scriptRecord 。
6. 将 scriptContext 的 VariableEnvironment 设为
globalEnv 。
7. 将 scriptContext 的 LexicalEnvironment 设为
globalEnv 。
8. 将 scriptContext 的 PrivateEnvironment 设为
null 。
9. 挂起 运行中的执行上下文 。
10. 将 scriptContext 推送到 执行上下文栈 ;此时
scriptContext 是 运行中的执行上下文 。
11. 将 script 设为 scriptRecord .[[ECMAScriptCode]] 。
12. 将 result 设为 Completion (GlobalDeclarationInstantiation (script ,
globalEnv ))。
13. 如果 result 是一个 正常完成 ,则
a. 将 result 设为 Completion (Evaluation of script )。
b. 如果 result 是一个 正常完成 且
result .[[Value]] 是 empty ,则
i. 将 result 设为 NormalCompletion (undefined )。
14. 挂起 scriptContext 并将其从 执行上下文栈 中移除。
15. Assert : 执行上下文栈 不能为空。
16. 恢复当前在 执行上下文栈 顶部的上下文作为 运行中的执行上下文 。
17. 返回 ? result 。
16.1.7 GlobalDeclarationInstantiation ( script , env )
抽象操作 GlobalDeclarationInstantiation 接受两个参数:script (一个 Script ,即脚本)和 env (一个 Global Environment
Record ,即全局环境记录),并返回一个正常完成记录或一个抛出完成记录。script 是正在建立执行上下文的脚本,env
是要创建绑定的全局环境。
注 1
在为脚本评估建立执行上下文时,声明会在当前全局环境中被实例化。代码中声明的每个全局绑定都会被实例化。
调用时执行以下步骤:
1. 令 lexNames 为 LexicallyDeclaredNames
的 script 。
2. 令 varNames 为 VarDeclaredNames
的 script 。
3. 对 lexNames 的每个元素 name 执行
a. 如果 env .HasVarDeclaration(name ) 为
true ,抛出 SyntaxError 异常。
b. 如果 env .HasLexicalDeclaration(name ) 为
true ,抛出 SyntaxError 异常。
c. 令 hasRestrictedGlobal 为
? env .HasRestrictedGlobalProperty(name )。
d. 如果 hasRestrictedGlobal 为 true ,抛出
SyntaxError 异常。
4. 对 varNames 的每个元素 name 执行
a. 如果 env .HasLexicalDeclaration(name ) 为
true ,抛出 SyntaxError 异常。
5. 令 varDeclarations 为 VarScopedDeclarations
的 script 。
6. 令 functionsToInitialize 为一个新的空的 List 。
7. 令 declaredFunctionNames 为一个新的空的 List 。
8. 对 varDeclarations 的每个元素 d (按逆序 List 顺序)执行
a. 如果 d 既不是 VariableDeclaration ,也不是
ForBinding ,或 BindingIdentifier ,则
i. Assert :d 是一个 FunctionDeclaration 、GeneratorDeclaration 、AsyncFunctionDeclaration ,或
AsyncGeneratorDeclaration 。
ii. 注意:如果有多个相同名称的函数声明,则使用最后一个声明。
iii. 令 fn 为 d 的唯一元素的 BoundNames 。
iv. 如果 declaredFunctionNames 中不包含 fn ,则
1. 令 fnDefinable 为
? env .CanDeclareGlobalFunction(fn )。
2. 如果 fnDefinable 为 false ,抛出
TypeError 异常。
3. 将 fn 添加到 declaredFunctionNames 中。
4. 将 d 作为第一个元素插入到
functionsToInitialize 中。
9. 令 declaredVarNames 为一个新的空的 List 。
10. 对 varDeclarations 的每个元素 d 执行
a. 如果 d 是 VariableDeclaration 、ForBinding ,或
BindingIdentifier ,则
i. 对 d 的 BoundNames
的每个字符串 vn 执行
1. 如果 declaredFunctionNames 中不包含
vn ,则
a. 令 vnDefinable 为
? env .CanDeclareGlobalVar(vn )。
b. 如果 vnDefinable 为
false ,抛出 TypeError 异常。
c. 如果 declaredVarNames 中不包含 vn ,则
i. 将 vn 添加到 declaredVarNames
中。
11. 注意:如果 global object 是一个 ordinary
object ,则此算法步骤不会发生异常终止。然而,如果 global object 是一个 Proxy exotic
object ,它可能表现出导致后续步骤异常终止的行为。
12.
注意:附录 B.3.2.2
在此处添加了额外的步骤。
13. 令 lexDeclarations 为 LexicallyScopedDeclarations
的 script 。
14. 令 privateEnv 为 null 。
15. 对 lexDeclarations 的每个元素 d 执行
a. 注意:词法声明的名称仅在此处实例化,但不会初始化。
b. 对 d 的 BoundNames 的每个元素
dn 执行
i. 如果 IsConstantDeclaration
为 true ,则
1. 执行 ? env .CreateImmutableBinding (dn ,
true )。
ii. 否则,
1. 执行 ? env .CreateMutableBinding (dn ,
false )。
16. 对 functionsToInitialize 的每个 Parse Node f 执行
a. 令 fn 为 f 的唯一元素的 BoundNames 。
b. 令 fo 为 InstantiateFunctionObject
的 f ,参数为 env 和 privateEnv 。
c. 执行 ? env .CreateGlobalFunctionBinding (fn ,
fo , false )。
17. 对 declaredVarNames 的每个字符串 vn 执行
a. 执行 ? env .CreateGlobalVarBinding (vn ,
false )。
18. 返回 unused 。
注 2
早期错误 在 16.1.1
中规定,防止函数/变量声明与 let/const/class 声明之间的名称冲突以及同一 脚本 中 let/const/class 绑定的重新声明。然而,跨多个
脚本 的此类冲突和重新声明会在
GlobalDeclarationInstantiation 期间被检测为运行时错误。如果检测到任何此类错误,则不会为脚本实例化任何绑定。然而,如果 全局对象 是通过 Proxy 异otic 对象
定义的,那么运行时对冲突声明的测试可能不可靠,导致 突然完成
和一些全局声明未被实例化。如果发生这种情况,脚本 的代码将不会被评估。
与显式的 var 或函数声明不同,直接在 全局对象 上创建的属性会导致全局绑定,这些绑定可能会被
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 静态语义:导入的本地名称 ( importEntries )
抽象操作 ImportedLocalNames 接受参数 importEntries (一个 List 的
ImportEntry Records )并返回一个 List 的字符串。它创建一个
List 包含
importEntries 定义的所有本地名称绑定。调用时执行以下步骤:
1. 令 localNames 为一个空的新 List 。
2. 对于每个 ImportEntry Record
i 属于 importEntries ,执行
a. 将 i .[[LocalName]] 追加到
localNames 。
3. 返回 localNames 。
16.2.1.3 静态语义:ModuleRequests
ModuleRequests 是一个 语法导向操作 ,不接受参数并返回一个
List
的字符串。它在以下产生式上逐段定义:
Module :
[empty]
1. 返回一个新的空 List 。
ModuleItemList
: ModuleItem
1. 返回 ModuleRequests
的 ModuleItem 。
ModuleItemList
:
ModuleItemList
ModuleItem
1. 令 moduleNames 为 ModuleRequests
的 ModuleItemList 。
2. 令 additionalNames 为 ModuleRequests
的 ModuleItem 。
3. 对于 additionalNames 中的每个字符串 name ,执行
a. 如果 moduleNames 不包含 name ,则
i. 将 name 追加到 moduleNames 。
4. 返回 moduleNames 。
ModuleItem
: StatementListItem
1. 返回一个新的空 List 。
ImportDeclaration
:
import
ImportClause
FromClause
;
1. 返回 ModuleRequests
的 FromClause 。
ModuleSpecifier
: StringLiteral
1. 返回一个 List ,其唯一元素是
SV 的 StringLiteral 。
ExportDeclaration
:
export
ExportFromClause
FromClause
;
1. 返回 ModuleRequests
的 FromClause 。
ExportDeclaration
:
export
NamedExports
;
export
VariableStatement
export
Declaration
export
default
HoistableDeclaration
export
default
ClassDeclaration
export
default
AssignmentExpression
;
1. 返回一个新的空 List 。
16.2.1.4 抽象模块记录
一个 模块记录
封装了单个模块的导入和导出的结构信息。这些信息用于链接一组连接模块的导入和导出。模块记录包括四个字段,这些字段仅在评估模块时使用。
为了规范目的,模块记录值是 Record
规范类型的值,可以被认为是存在于一个简单的面向对象层次结构中,其中模块记录是一个抽象类,既有抽象也有具体的子类。本规范定义了名为 Cyclic Module
Record 的抽象子类及其具体子类 Source Text Module
Record 。其他规范和实现可以定义与它们定义的替代模块定义设施相对应的附加模块记录子类。
模块记录定义了 表 41
中列出的字段。所有模块定义子类至少包括这些字段。模块记录还定义了 表
42 中的抽象方法列表。所有模块定义子类必须提供这些抽象方法的具体实现。
表 41: 模块记录 字段
表 42: 模块记录 的抽象方法
方法
目的
LoadRequestedModules( [ hostDefined ] )
通过递归加载所有依赖项来准备模块进行链接,并返回一个承诺。
GetExportedNames([exportStarSet ])
返回从此模块直接或间接导出的所有名称的列表。
在调用此方法之前,LoadRequestedModules 必须成功完成。
ResolveExport(exportName [, resolveSet ])
返回此模块导出的名称的绑定。绑定由 ResolvedBinding Record 表示,形式为 { [[Module]] :
模块记录 , [[BindingName]] : 字符串 | namespace
}。如果导出是一个在任何模块中没有直接绑定的模块命名空间对象,[[BindingName]] 将设置为
namespace 。如果名称无法解析,则返回 null ,如果找到多个绑定,则返回
ambiguous 。
每次使用特定的 exportName 和 resolveSet 对调用此操作时,必须返回相同的结果。
在调用此方法之前,LoadRequestedModules 必须成功完成。
Link()
通过传递解决所有模块依赖项并创建一个 模块环境记录 ,准备模块进行评估。
在调用此方法之前,LoadRequestedModules 必须成功完成。
Evaluate()
返回此模块及其依赖项评估的承诺,成功评估或已成功评估时解析,评估错误或已失败评估时拒绝。如果承诺被拒绝,宿主 应处理承诺拒绝并重新抛出评估错误。
在调用此方法之前,Link 必须成功完成。
16.2.1.5 循环模块记录
一个 循环模块记录
用于表示关于一个模块的信息,该模块可以与其他 循环模块记录 类型的子类模块形成依赖循环。不是 循环模块记录 类型的子类的 模块记录 不得与 源文本模块记录 形成依赖循环。
除了在 表 41 中定义的字段外,循环模块记录 还有 表 43 中列出的附加字段。
表 43: 循环模块记录 的附加字段
字段名称
值类型
含义
[[Status]]
new , unlinked , linking ,
linked , evaluating ,
evaluating-async ,
or evaluated
最初为 new 。过渡到 unlinked ,
linking ,
linked , evaluating ,可能为
evaluating-async ,
evaluated (按此顺序),因为模块在其生命周期中进展。evaluating-async
表示此模块在完成其异步依赖项后排队执行,或者它是一个 [[HasTLA]] 字段为 true
的模块,已执行并等待顶级完成。
[[EvaluationError]]
一个 throw
completion 或 empty
一个 throw
completion ,表示评估期间发生的异常。如果没有发生异常或 [[Status]] 不是
evaluated ,则为 undefined 。
[[DFSIndex]]
一个 integer 或
empty
仅在链接和评估期间使用的辅助字段。如果 [[Status]] 是 linking 或
evaluating ,这个非负数记录了模块在依赖图深度优先遍历中首次被访问的点。
[[DFSAncestorIndex]]
一个 integer 或
empty
仅在链接和评估期间使用的辅助字段。如果 [[Status]] 是 linking 或
evaluating ,这要么是模块自己的 [[DFSIndex]] ,要么是同一强连通分量中“较早”模块的 [[DFSIndex]] 。
[[RequestedModules]]
一个 List
的字符串
一个 List ,包含此记录表示的模块用于请求导入模块的所有
ModuleSpecifier 字符串。该
List
按源文本出现顺序排列。
[[LoadedModules]]
一个 List
的 Records
包含字段 [[Specifier]] (一个字符串)和 [[Module]] (一个
Module Record )
一个从此记录表示的模块使用的指定符字符串到解析的 Module Record
的映射。该列表不包含两个不同的 Records
具有相同的 [[Specifier]] 。
[[CycleRoot]]
一个 Cyclic Module Record 或
empty
循环中第一个访问的模块,强连通分量的根 DFS 祖先。对于不在循环中的模块,这将是模块本身。一旦 Evaluate 完成,模块的 [[DFSAncestorIndex]] 是其 [[CycleRoot]] 的 [[DFSIndex]] 。
[[HasTLA]]
一个布尔值
此模块是否是单独异步的(例如,如果它是一个包含顶层 await 的 Source Text Module
Record )。具有异步依赖并不意味着此字段为 true 。此字段在模块解析后不得更改。
[[AsyncEvaluation]]
一个布尔值
此模块是否本身是异步的或有异步依赖。注意:此字段设置的顺序用于排序排队执行,参见 16.2.1.5.3.4 。
[[TopLevelCapability]]
一个 PromiseCapability
Record 或 empty
如果此模块是某个循环的 [[CycleRoot]] ,并且在那个循环中的某个模块上调用了 Evaluate(),此字段包含整个评估的
PromiseCapability
Record 。它用于解决从 Evaluate() 抽象方法返回的 Promise 对象。对于该模块的任何依赖项,此字段将为
empty ,除非已为某些依赖项启动了顶层 Evaluate()。
[[AsyncParentModules]]
一个 List
的 Cyclic Module Records
如果此模块或其依赖项有 [[HasTLA]] 为
true ,并且执行正在进行中,这会跟踪此模块的父导入者,用于顶层执行作业。这些父模块在
此模块成功完成执行之前不会开始执行。
[[PendingAsyncDependencies]]
一个 integer 或
empty
如果此模块有任何异步依赖项,这会跟踪此模块剩余的异步依赖模块数量。具有异步依赖项的模块将在此字段达到 0 且没有执行错误时执行。
除了在 表 42
中定义的方法外,循环模块记录 还有 表 44 中列出的附加方法。
表 44: 循环模块记录 的附加抽象方法
一个 GraphLoadingState Record 是一个 Record ,包含有关模块图加载过程的信息。它用于在调用
HostLoadImportedModule
之后继续加载。每个 GraphLoadingState Record 具有
表 45 中定义的字段:
表 45: GraphLoadingState Record
字段
16.2.1.5.1 LoadRequestedModules ( [ hostDefined ] )
LoadRequestedModules 的具体方法来自 循环模块记录
module ,接受一个可选的 hostDefined 参数(任何类型)并返回一个 Promise。它填充 module 依赖图中所有
模块记录 的 [[LoadedModules]] (大部分工作由辅助函数 InnerModuleLoading
完成)。它接受一个可选的 hostDefined 参数,并传递给 HostLoadImportedModule
钩子。调用时执行以下步骤:
1. 如果 hostDefined 不存在,则让 hostDefined 为
empty 。
2. 让 pc 为 ! NewPromiseCapability (%Promise% )。
3. 让 state 为 图加载状态记录
{ [[IsLoading]] : true , [[PendingModulesCount]] : 1, [[Visited]] : « »,
[[PromiseCapability]] : pc , [[HostDefined]] : hostDefined }。
4. 执行 InnerModuleLoading (state ,
module )。
5. 返回 pc .[[Promise]] 。
备注
hostDefined 参数可用于传递获取导入模块所需的额外信息。例如,HTML 使用它来设置
<link rel="preload" as="...">
标签的正确获取目标。import()
表达式从不设置
hostDefined 参数。
16.2.1.5.1.1 InnerModuleLoading ( state , module )
抽象操作 InnerModuleLoading 接受 state (一个 图加载状态记录 )和
module (一个 模块记录 )作为参数,并返回
unused 。它由 LoadRequestedModules 用于递归执行 module 的依赖图的实际加载过程。调用时执行以下步骤:
1. 断言 : state .[[IsLoading]] 为 true 。
2. 如果 module 是一个 循环模块记录 ,module .[[Status]] 为 new ,并且 state .[[Visited]] 不包含 module ,则
a. 将 module 添加到 state .[[Visited]] 。
b. 让 requestedModulesCount 为
module .[[RequestedModules]] 中的元素数量。
c. 将 state .[[PendingModulesCount]] 设置为 state .[[PendingModulesCount]] + requestedModulesCount 。
d. 对于 module .[[RequestedModules]] 中的每个字符串 required ,执行
i. 如果 module .[[LoadedModules]] 包含一个 记录
其 [[Specifier]] 为 required ,则
1. 让 record 为该 记录 。
2. 执行 InnerModuleLoading (state ,
record .[[Module]] )。
ii. 否则,
1. 执行 HostLoadImportedModule (module ,
required , state .[[HostDefined]] ,
state )。
2. 备注:HostLoadImportedModule
将调用 FinishLoadingImportedModule ,其通过
ContinueModuleLoading
重新进入图加载过程。
iii. 如果 state .[[IsLoading]] 为 false ,则返回
unused 。
3. 断言 : state .[[PendingModulesCount]] ≥ 1。
4. 将 state .[[PendingModulesCount]] 设置为 state .[[PendingModulesCount]] - 1。
5. 如果 state .[[PendingModulesCount]] = 0,则
a. 将 state .[[IsLoading]]
设置为 false 。
b. 对于 state .[[Visited]]
中的每个 循环模块记录
loaded ,执行
i. 如果 loaded .[[Status]] 为 new ,则将 loaded .[[Status]] 设置为 unlinked 。
c. 执行 ! Call (state .[[PromiseCapability]] .[[Resolve]] ,
undefined , « undefined »)。
6. 返回 unused 。
16.2.1.5.1.2 ContinueModuleLoading ( state ,
moduleCompletion )
抽象操作 ContinueModuleLoading 接受 state (一个 图加载状态记录 )和
moduleCompletion (一个 包含 一个
模块记录 的正常完成记录或一个
抛出完成 )作为参数并返回
unused 。它用于在调用 HostLoadImportedModule
后重新进入加载过程。调用时执行以下步骤:
1. 如果 state .[[IsLoading]] 为
false ,则返回 unused 。
2. 如果 moduleCompletion 是一个 正常完成 ,则
a. 执行 InnerModuleLoading (state ,
moduleCompletion .[[Value]] )。
3. 否则,
a. 将 state .[[IsLoading]]
设置为 false 。
b. 执行 ! Call (state .[[PromiseCapability]] .[[Reject]] ,
undefined , « moduleCompletion .[[Value]] »)。
4. 返回 unused 。
16.2.1.5.2 Link ( )
一个循环模块记录
module 的 Link 具体方法不接受参数,并返回一个包含
unused 的正常完成记录,或一个抛出完成 。成功时,Link
将此模块的[[Status]] 从unlinked 转换为
linked 。
失败时,会抛出异常,此模块的[[Status]] 保持为
unlinked 。(大部分工作由辅助函数InnerModuleLinking 完成。)它
执行以下步骤:
1. 断言 :module .[[Status]] 是unlinked 、
linked 、evaluating-async 或
evaluated 之一。
2. 让stack 成为一个新的空List 。
3. 让result 成为Completion (InnerModuleLinking (module ,
stack , 0))。
4. 如果result 是abrupt
completion ,则
a. 对于stack 中的每个循环模块记录 m ,执行
i. 断言 :m .[[Status]] 是linking 。
ii. 将m .[[Status]]
设置为unlinked 。
b. 断言 :module .[[Status]] 是unlinked 。
c. 返回 ? result 。
5. 断言 :module .[[Status]] 是linked 、
evaluating-async 或evaluated 之一。
6. 断言 :stack 为空。
7. 返回unused 。
16.2.1.5.2.1 InnerModuleLinking ( module ,
stack ,
index )
抽象操作 InnerModuleLinking 接受参数module (一个Module
Record ),
stack (一个List ,
Cyclic Module Records ),
和index (一个非负integer ),返回一个
包含 非负
integer 的正常完成记录,或一个抛出完成 。它被
Link 用来对
module 执行实际的链接过程,并递归地对依赖图中的所有其他模块执行。stack 和
index 参数,以及模块的[[DFSIndex]] 和[[DFSAncestorIndex]] 字段,用于跟踪深度优先搜索(DFS)遍历。特别是,[[DFSAncestorIndex]] 用于发现强连通分量(SCC),使所有 SCC
中的模块一起转换为linked 。它在调用时执行以下步骤:
1. 如果module 不是Cyclic Module
Record ,则
a. 执行 ? module .Link()。
b. 返回index 。
2. 如果module .[[Status]]
是linking 、linked 、
evaluating-async 或evaluated 之一,则
a. 返回index 。
3. 断言 :module .[[Status]] 是unlinked 。
4. 设置module .[[Status]]
为linking 。
5. 设置module .[[DFSIndex]]
为index 。
6. 设置module .[[DFSAncestorIndex]] 为index 。
7. 将index 设置为index + 1。
8. 将module 附加到stack 。
9. 对于module .[[RequestedModules]] 中的每个字符串required ,执行
a. 让requiredModule 成为GetImportedModule (module ,
required )。
b. 将index 设置为 ? InnerModuleLinking (requiredModule ,
stack , index )。
c. 如果requiredModule 是Cyclic Module
Record ,则
i. 断言 :
requiredModule .[[Status]] 是linking 、linked 、
evaluating-async 或evaluated 之一。
ii. 断言 :
requiredModule .[[Status]] 是linking ,如果且仅如果stack 包含requiredModule 。
iii. 如果requiredModule .[[Status]] 是linking ,则
1. 设置module .[[DFSAncestorIndex]] 为min (module .[[DFSAncestorIndex]] , requiredModule .[[DFSAncestorIndex]] )。
10. 执行 ? module .InitializeEnvironment()。
11. 断言 :module 在stack 中只出现一次。
12. 断言 :module .[[DFSAncestorIndex]] ≤ module .[[DFSIndex]] 。
13. 如果module .[[DFSAncestorIndex]] = module .[[DFSIndex]] ,则
a. 将done 设为false 。
b. 重复,当done 为false 时,
i. 让requiredModule 成为stack 的最后一个元素。
ii. 移除stack 的最后一个元素。
iii. 断言 :
requiredModule 是一个循环模块记录 。
iv. 将requiredModule .[[Status]] 设置为linked 。
v.
如果requiredModule 和module 是相同的模块记录 ,将done 设置为true 。
14. 返回index 。
16.2.1.5.3 Evaluate ( )
module 的 Cyclic Module Record
的 Evaluate 具体方法不接受参数并返回一个 Promise。Evaluate 将此模块的 [[Status]] 从
linked 转换为 evaluating-async 或
evaluated 。
第一次在给定的强连通分量中的模块上调用时,Evaluate 创建并返回一个 Promise,当模块完成评估时,该 Promise 将被解析。
这个 Promise 被存储在组件的 [[CycleRoot]] 的 [[TopLevelCapability]] 字段中。
在组件中的任何模块上再次调用 Evaluate 时,返回相同的 Promise。
(大部分工作由辅助函数 InnerModuleEvaluation 完成。)
调用时执行以下步骤:
1. 断言 :Evaluate 的这次调用不会与 周围代理 内的另一 Evaluate 调用同时进行。
2. 断言 :module .[[Status]] 是
linked 、evaluating-async 或
evaluated 之一。
3. 如果 module .[[Status]] 是
evaluating-async 或 evaluated ,则将 module 设置为
module .[[CycleRoot]] 。
4. 如果 module .[[TopLevelCapability]] 不是 empty ,则
a. 返回 module .[[TopLevelCapability]] .[[Promise]] 。
5. 让 stack 成为一个新的空 列表 。
6. 让 capability 成为 ! NewPromiseCapability (%Promise% )。
7. 将 module .[[TopLevelCapability]] 设置为 capability 。
8. 让 result 成为 完成 (InnerModuleEvaluation (module ,
stack , 0))。
9. 如果 result 是一个 突然完成 ,则
a. 对于 stack 中的每个 循环模块记录 m ,执行
i. 断言 :m .[[Status]] 是 evaluating 。
ii. 将 m .[[Status]] 设置为
evaluated 。
iii. 将 m .[[EvaluationError]] 设置为 result 。
b. 断言 :module .[[Status]] 是 evaluated 。
c. 断言 :module .[[EvaluationError]] 是 result 。
d. 执行 ! 调用 (capability .[[Reject]] ,undefined ,« result .[[Value]] »)。
10. 否则,
a. 断言 :module .[[Status]] 是 evaluating-async 或
evaluated 。
b. 断言 :module .[[EvaluationError]] 是 empty 。
c. 如果 module .[[AsyncEvaluation]] 是 false ,则
i. 断言 :module .[[Status]] 是 evaluated 。
ii. 执行 ! 调用 (capability .[[Resolve]] ,undefined ,«
undefined »)。
d. 断言 :stack 是空的。
11. 返回 capability .[[Promise]] 。
16.2.1.5.3.1 InnerModuleEvaluation ( module ,
stack , index )
抽象操作 InnerModuleEvaluation 接受参数 module (一个 模块记录 ),
stack (一个 列表 的
循环模块记录 ),
和 index (一个非负的 整数 )并返回一个
正常完成 ,包含一个非负的
整数
或一个 抛出完成 。
它被 Evaluate 用于执行 module 的实际评估过程,以及递归地处理依赖图中的所有其他模块。
stack 和 index 参数,以及 module 的 [[DFSIndex]] 和
[[DFSAncestorIndex]] 字段,
使用方式与 InnerModuleLinking 中相同。
调用时执行以下步骤:
1. 如果 module 不是一个 循环模块记录 ,则
a. 让 promise 成为
! module .Evaluate()。
b. 断言 :promise .[[PromiseState]] 不是 pending 。
c. 如果 promise .[[PromiseState]] 是 rejected ,则
i. 返回 ThrowCompletion (promise .[[PromiseResult]] )。
d. 返回 index 。
2. 如果 module .[[Status]] 是
evaluating-async 或 evaluated ,则
a. 如果 module .[[EvaluationError]] 是 empty ,返回
index 。
b. 否则,返回 ? module .[[EvaluationError]] 。
3. 如果 module .[[Status]] 是
evaluating ,返回 index 。
4. 断言 :module .[[Status]] 是 linked 。
5. 将 module .[[Status]] 设置为
evaluating 。
6. 将 module .[[DFSIndex]] 设置为
index 。
7. 将 module .[[DFSAncestorIndex]] 设置为 index 。
8. 将 module .[[PendingAsyncDependencies]] 设置为 0。
9. 将 index 设置为 index + 1。
10. 将 module 追加到 stack 。
11. 对于 module .[[RequestedModules]] 的每个字符串 required ,执行
a. 让 requiredModule 成为 GetImportedModule (module ,
required )。
b. 将 index 设置为 ? InnerModuleEvaluation (requiredModule ,
stack , index )。
c. 如果 requiredModule 是一个 循环模块记录 ,则
i. 断言 :requiredModule .[[Status]] 是
evaluating 、evaluating-async 或
evaluated 之一。
ii. 断言 :仅当 stack 包含
requiredModule 时,requiredModule .[[Status]]
才是 evaluating 。
iii. 如果 requiredModule .[[Status]] 是 evaluating ,则
1. 将 module .[[DFSAncestorIndex]] 设置为 最小值 (module .[[DFSAncestorIndex]] ,requiredModule .[[DFSAncestorIndex]] )。
iv. 否则,
1. 将 requiredModule 设置为
requiredModule .[[CycleRoot]] 。
2. 断言 :requiredModule .[[Status]] 是 evaluating-async 或
evaluated 。
3. 如果 requiredModule .[[EvaluationError]] 不是 empty ,返回
? requiredModule .[[EvaluationError]] 。
v. 如果 requiredModule .[[AsyncEvaluation]] 是 true ,则
1. 将 module .[[PendingAsyncDependencies]] 设置为 module .[[PendingAsyncDependencies]] + 1。
2. 将 module 追加到
requiredModule .[[AsyncParentModules]] 。
12. 如果 module .[[PendingAsyncDependencies]] > 0 或 module .[[HasTLA]] 是 true ,则
a. 断言 :module .[[AsyncEvaluation]] 是 false 并且从未被设置为
true 。
b. 将 module .[[AsyncEvaluation]] 设置为 true 。
c. 注意:模块记录的 [[AsyncEvaluation]]
字段转换为 true 的顺序是重要的。
d. 如果 module .[[PendingAsyncDependencies]] = 0,执行 ExecuteAsyncModule (module )。
13. 否则,
a. 执行 ? module .ExecuteModule() 。
14. 断言 :module 在 stack
中恰好出现一次。
15. 断言 :module .[[DFSAncestorIndex]] ≤ module .[[DFSIndex]] 。
16. 如果 module .[[DFSAncestorIndex]] = module .[[DFSIndex]] ,则
a. 让 done 为 false 。
b. 重复,直到 done 为 false ,
i. 让 requiredModule 成为 stack
的最后一个元素。
ii. 移除 stack 的最后一个元素。
iii. 断言 :requiredModule
是一个 循环模块记录 。
iv. 如果 requiredModule .[[AsyncEvaluation]] 是 false ,将
requiredModule .[[Status]] 设置为
evaluated 。
v. 否则,将 requiredModule .[[Status]] 设置为 evaluating-async 。
vi. 如果 requiredModule 和 module
是相同的 模块记录 ,将
done 设置为 true 。
vii. 将 requiredModule .[[CycleRoot]] 设置为 module 。
17. 返回 index 。
注1
模块在被 InnerModuleEvaluation 遍历时处于 evaluating 状态。
模块在执行完成时处于 evaluated 状态,或者在执行期间如果其 [[HasTLA]] 字段为
true 或它有异步依赖项时处于 evaluating-async 状态。
注2
当一个异步循环中的模块不处于 evaluating 状态时,任何依赖该模块的模块将依赖于循环根模块的执行状态。
这确保了循环状态可以通过其根模块状态被视为单个强连通分量。
16.2.1.5.3.2 ExecuteAsyncModule ( module )
抽象操作 ExecuteAsyncModule 接受参数 module (一个 循环模块记录 ),
并返回 unused 。调用时执行以下步骤:
1. 断言 :module .[[Status]] 是 evaluating 或
evaluating-async 。
2. 断言 :module .[[HasTLA]] 是 true 。
3. 让 capability 成为 ! NewPromiseCapability (%Promise% )。
4. 让 fulfilledClosure 成为一个新的 抽象闭包 ,不带参数,捕获
module 并在调用时执行以下步骤:
a. 执行 AsyncModuleExecutionFulfilled (module )。
b. 返回 undefined 。
5. 让 onFulfilled 成为 CreateBuiltinFunction (fulfilledClosure ,
0,"" ,« »)。
6. 让 rejectedClosure 成为一个新的 抽象闭包 ,带参数
(error ),捕获 module 并在调用时执行以下步骤:
a. 执行 AsyncModuleExecutionRejected (module ,
error )。
b. 返回 undefined 。
7. 让 onRejected 成为 CreateBuiltinFunction (rejectedClosure ,
0,"" ,« »)。
8. 执行 PerformPromiseThen (capability .[[Promise]] ,onFulfilled ,onRejected )。
9. 执行 ! module .ExecuteModule (capability )。
10. 返回 unused 。
16.2.1.5.3.3 GatherAvailableAncestors ( module ,
execList )
抽象操作 GatherAvailableAncestors 接受参数 module (一个 循环模块记录 )和
execList (一个 列表 的
循环模块记录 )
并返回 unused 。调用时执行以下步骤:
1. 对于 module .[[AsyncParentModules]] 的每个 循环模块记录
m ,执行
a. 如果 execList 不包含 m 且
m .[[CycleRoot]] .[[EvaluationError]] 是 empty ,则
i. 断言 :m .[[Status]] 是 evaluating-async 。
ii. 断言 :m .[[EvaluationError]] 是 empty 。
iii. 断言 :m .[[AsyncEvaluation]] 是 true 。
iv. 断言 :m .[[PendingAsyncDependencies]] > 0。
v. 将 m .[[PendingAsyncDependencies]] 设置为 m .[[PendingAsyncDependencies]] - 1。
vi. 如果 m .[[PendingAsyncDependencies]] = 0,则
1. 将 m 追加到 execList 。
2. 如果 m .[[HasTLA]] 是 false ,执行 GatherAvailableAncestors (m ,
execList )。
2. 返回 unused 。
注
当根 module 的异步执行完成时,此函数确定能够同步执行的模块列表,并将它们填充到 execList 中。
16.2.1.5.3.4 AsyncModuleExecutionFulfilled ( module )
抽象操作 AsyncModuleExecutionFulfilled 接受参数 module (一个
循环模块记录 ),
并返回 unused 。调用时执行以下步骤:
1. 如果 module .[[Status]] 是
evaluated ,则
a. 断言 :module .[[EvaluationError]] 不是 empty 。
b. 返回 unused 。
2. 断言 :module .[[Status]] 是 evaluating-async 。
3. 断言 :module .[[AsyncEvaluation]] 是 true 。
4. 断言 :module .[[EvaluationError]] 是 empty 。
5. 将 module .[[AsyncEvaluation]] 设置为 false 。
6. 将 module .[[Status]] 设置为
evaluated 。
7. 如果 module .[[TopLevelCapability]] 不是 empty ,则
a. 断言 :module .[[CycleRoot]] 是 module 。
b. 执行 ! 调用 (module .[[TopLevelCapability]] .[[Resolve]] ,undefined ,«
undefined »)。
8. 让 execList 成为一个新的空 列表 。
9. 执行 GatherAvailableAncestors (module ,
execList )。
10. 让 sortedExecList 成为一个 列表 ,其元素是
execList 的元素,按它们在 InnerModuleEvaluation
中将其 [[AsyncEvaluation]] 字段设置为 true 的顺序排列。
11. 断言 :sortedExecList 的所有元素都已将其
[[AsyncEvaluation]] 字段设置为 true ,其 [[PendingAsyncDependencies]] 字段设置为 0,其 [[EvaluationError]] 字段设置为 empty 。
12. 对于 sortedExecList 的每个 循环模块记录 m ,执行
a. 如果 m .[[Status]] 是
evaluated ,则
i. 断言 :m .[[EvaluationError]] 不是 empty 。
b. 如果 m .[[HasTLA]] 是
true ,则
i. 执行 ExecuteAsyncModule (m )。
c. 否则,
i. 让 result 成为 m .ExecuteModule() 。
ii. 如果 result 是一个 突然完成 ,则
1. 执行 AsyncModuleExecutionRejected (m ,
result .[[Value]] )。
iii. 否则,
1. 将 m .[[Status]] 设置为 evaluated 。
2. 如果 m .[[TopLevelCapability]] 不是 empty ,则
a. 断言 :m .[[CycleRoot]] 是 m 。
b. 执行 ! 调用 (m .[[TopLevelCapability]] .[[Resolve]] ,undefined ,«
undefined »)。
13. 返回 unused 。
16.2.1.5.3.5 AsyncModuleExecutionRejected ( module ,
error )
抽象操作 AsyncModuleExecutionRejected 接受参数 module (一个
循环模块记录 )和
error (一个 ECMAScript 语言值 ),
并返回 unused 。调用时执行以下步骤:
1. 如果 module .[[Status]] 是
evaluated ,则
a. 断言 :module .[[EvaluationError]] 不是 empty 。
b. 返回 unused 。
2. 断言 :module .[[Status]] 是 evaluating-async 。
3. 断言 :module .[[AsyncEvaluation]] 是 true 。
4. 断言 :module .[[EvaluationError]] 是 empty 。
5. 将 module .[[EvaluationError]] 设置为 ThrowCompletion (error )。
6. 将 module .[[Status]] 设置为
evaluated 。
7. 对于 module .[[AsyncParentModules]] 的每个 循环模块记录
m ,执行
a. 执行 AsyncModuleExecutionRejected (m ,
error )。
8. 如果 module .[[TopLevelCapability]] 不是 empty ,则
a. 断言 :module .[[CycleRoot]] 是 module 。
b. 执行 ! 调用 (module .[[TopLevelCapability]] .[[Reject]] ,undefined ,« error »)。
9. 返回 unused 。
16.2.1.5.4 循环模块记录图示例
本非规范性章节提供了一系列常见模块图的链接和评估示例,特别关注错误发生的方式。
首先考虑以下简单模块图:
图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()之后。如果InnerModuleLinking
的C 成功,但随后B 失败,例如因为它导入了C 未提供的内容,那么最初的A .Link()将失败,并且A 和B 的[[Status]] 保持unlinked 。不过,C 的[[Status]] 已变为linked 。
最后,考虑在成功调用Link()后发生评估错误的情况。如果InnerModuleEvaluation
的C 成功,但随后B 失败,例如因为B 包含抛出异常的代码,那么最初的A .Evaluate()将失败,返回一个被拒绝的Promise。结果异常将记录在A 和B 的[[EvaluationError]] 字段中,并且它们的[[Status]] 将变为evaluated 。不过,C 也将变为evaluated ,但与A 和B 不同,它将不会有[[EvaluationError]] ,因为它成功完成了评估。存储异常确保任何时候宿主 尝试通过调用它们的Evaluate()方法重用A 或B 时,它将遇到相同的异常。(宿主 不需要重用循环模块记录 ;同样,宿主 也不需要暴露这些方法抛出的异常对象。然而,规范允许这种使用。)
现在考虑一种不同类型的错误条件:
图3:一个无法解析的模块图
在这种情况下,模块A 声明依赖于某个其他模块,但没有该模块的模块记录 ,即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()会调用InnerModuleEvaluation ,对A 、B 和D 执行,它们都会过渡到evaluating 。然后对A 再次调用InnerModuleEvaluation ,这是一个无操作,因为它已经在evaluating 。此时,D .[[PendingAsyncDependencies]] 为0,因此调用ExecuteAsyncModule (D )并调用D .ExecuteModule,使用一个新的PromiseCapability跟踪D 的异步执行。我们回到InnerModuleEvaluation ,对B 进行设置,将B .[[PendingAsyncDependencies]] 设置为1,将B .[[AsyncEvaluation]] 设置为true 。我们再次返回到对A 的原始InnerModuleEvaluation ,将A .[[PendingAsyncDependencies]] 设置为1。在对A 依赖项的循环的下一次迭代中,我们调用InnerModuleEvaluation 对C 和D (再次无操作)以及E 进行设置。由于E 没有依赖项并且不属于循环,我们以与D 相同的方式调用ExecuteAsyncModule (E ),E 立即从堆栈中移除。我们再次返回到对A 的原始InnerModuleEvaluation ,将C .[[AsyncEvaluation]] 设置为true 。现在我们完成了对A 依赖项的循环,将A .[[AsyncEvaluation]] 设置为true ,并将整个强连通分量从堆栈中移除,将所有模块同时过渡到evaluating-async 。此时,模块的字段如下表表46 所示。
表46:初始Evaluate()调用后的模块字段
模块
[[DFSIndex]]
[[DFSAncestorIndex]]
[[Status]]
[[AsyncEvaluation]]
[[AsyncParentModules]]
[[PendingAsyncDependencies]]
A
0
0
evaluating-async
true
« »
2 (B 和C )
B
1
0
evaluating-async
true
« A »
1 (D )
C
2
0
evaluating-async
true
« A »
2 (D 和E )
D
3
0
evaluating-async
true
« B ,C »
0
E
4
4
evaluating-async
true
« C »
0
我们假设E 首先完成执行。当这种情况发生时,调用AsyncModuleExecutionFulfilled ,将E .[[Status]] 设置为evaluated 并将C .[[PendingAsyncDependencies]] 递减为1。更新后的模块字段如下表表47 所示。
表47:模块E 完成执行后的模块字段
模块
[[DFSIndex]]
[[DFSAncestorIndex]]
[[Status]]
[[AsyncEvaluation]]
[[AsyncParentModules]]
[[PendingAsyncDependencies]]
C
2
0
evaluating-async
< emu-val>true
« A »
1 (D )
E
4
4
evaluated
true
« C »
0
D 是下一个完成的模块(因为它是唯一仍在执行的模块)。当这种情况发生时,再次调用AsyncModuleExecutionFulfilled ,并将D .[[Status]] 设置为evaluated 。然后B .[[PendingAsyncDependencies]] 递减为0,调用ExecuteAsyncModule ,并开始执行。C .[[PendingAsyncDependencies]] 也递减为0,C 开始执行(如果B 包含一个await
,则可能与B 并行执行)。更新后的模块字段如下表表48 所示。
表48:模块D 完成执行后的模块字段
模块
[[DFSIndex]]
[[DFSAncestorIndex]]
[[Status]]
[[AsyncEvaluation]]
[[AsyncParentModules]]
[[PendingAsyncDependencies]]
B
1
0
evaluating-async
true
« A »
0
C
2
0
evaluating-async
true
« A »
0
D
3
0
evaluated
true
« B ,C »
0
我们假设C 接下来完成执行。当这种情况发生时,再次调用AsyncModuleExecutionFulfilled ,将C .[[Status]] 设置为evaluated 并将A .[[PendingAsyncDependencies]] 递减为1。更新后的模块字段如下表表49 所示。
表49:模块C 完成执行后的模块字段
模块
[[DFSIndex]]
[[DFSAncestorIndex]]
[[Status]]
[[AsyncEvaluation]]
[[AsyncParentModules]]
[[PendingAsyncDependencies]]
A
0
0
evaluating-async
true
« »
1 (B )
C
2
0
evaluated
true
« A »
0
然后,B 完成执行。当这种情况发生时,再次调用AsyncModuleExecutionFulfilled ,并将B .[[Status]] 设置为evaluated 。A .[[PendingAsyncDependencies]] 递减为0,因此调用ExecuteAsyncModule 并开始执行。更新后的模块字段如下表表50 所示。
表50:模块B 完成执行后的模块字段
模块
[[DFSIndex]]
[[DFSAncestorIndex]]
[[Status]]
[[AsyncEvaluation]]
[[AsyncParentModules]]
[[PendingAsyncDependencies]]
A
0
0
evaluating-async
true
« »
0
B
1
0
evaluated
true
« A »
0
最后,A 完成执行。当这种情况发生时,再次调用AsyncModuleExecutionFulfilled ,并将A .[[Status]] 设置为evaluated 。此时,A .[[TopLevelCapability]] 中的Promise(由A .Evaluate()返回)会被解析,从而结束了此模块图的处理。更新后的模块字段如下表表51 所示。
表51:模块A 完成执行后的模块字段
模块
[[DFSIndex]]
[[DFSAncestorIndex]]
[[Status]]
[[AsyncEvaluation]]
[[AsyncParentModules]]
[[PendingAsyncDependencies]]
A
0
0
evaluated
true
« »
0
或者,考虑一种失败情况,其中C 在B 完成执行之前返回错误。当这种情况发生时,调用AsyncModuleExecutionRejected ,将C .[[Status]] 设置为evaluated 并将C .[[EvaluationError]] 设置为错误。然后通过对所有AsyncParentModules 执行AsyncModuleExecutionRejected 来传播此错误。更新后的模块字段如下表表52 所示。
表52:模块C 执行出错后的模块字段
模块
[[DFSIndex]]
[[DFSAncestorIndex]]
[[Status]]
[[AsyncEvaluation]]
[[AsyncParentModules]]
[[PendingAsyncDependencies]]
[[EvaluationError]]
A
0
0
evaluated
true
« »
1 (B )
empty
C
2
1
evaluated
true
« A »
0
C 的评估错误
A 将因与C 相同的错误被拒绝,因为C 将使用C 的错误对A 调用AsyncModuleExecutionRejected 。A .[[Status]] 设置为evaluated 。此时,A .[[TopLevelCapability]] 中的Promise(由A .Evaluate()返回)被拒绝。更新后的模块字段如下表表53 所示。
表53:模块A 被拒绝后的模块字段
模块
[[DFSIndex]]
[[DFSAncestorIndex]]
[[Status]]
[[AsyncEvaluation]]
[[AsyncParentModules]]
[[PendingAsyncDependencies]]
[[EvaluationError]]
A
0
0
evaluated
true
« »
0
C 的评估 错误
然后,B 在没有错误的情况下完成执行。当这种情况发生时,再次调用AsyncModuleExecutionFulfilled ,并将B .[[Status]] 设置为evaluated 。然后对B 调用GatherAvailableAncestors 。然而,A .[[CycleRoot]] 是A ,它有评估错误,因此不会被添加到返回的sortedExecList 中,并且AsyncModuleExecutionFulfilled 将返回而不进行进一步处理。B 的任何未来导入者将从评估错误中解决B .[[CycleRoot]] .[[EvaluationError]] 。更新后的模块字段如下表表54 所示。
表54:模块B 在错误图中完成执行后的模块字段
模块
[[DFSIndex]]
[[DFSAncestorIndex]]
[[Status]]
[[AsyncEvaluation]]
[[AsyncParentModules]]
[[PendingAsyncDependencies]]
[[EvaluationError]]
A
0
0
evaluated
true
« »
0
C 的评估 错误
B
1
0
evaluated
true
« A »
0
empty
16.2.1.6 源文本模块记录
源文本模块记录用于表示从 ECMAScript 源文本 (11 )
解析的模块信息。其字段包含关于模块中导入和导出名称的信息,并使用这些信息来链接和评估模块。
源文本模块记录可以与 抽象模块记录
类型的其他子类一起存在于模块图中,并且可以与 循环模块记录 类型的其他子类一起参与循环。
除了在 表 43 中定义的字段之外,源文本模块记录 还具有 表
55 中列出的附加字段。每个字段最初都在 ParseModule 中设置。
表 55:源文本模块记录 的附加字段
字段名称
值类型
含义
[[ECMAScriptCode]]
解析节点
使用 Module
作为目标符号解析此模块的源文本的结果。
[[Context]]
ECMAScript 代码执行上下文 或
empty
与此模块相关的 执行上下文 。在模块的环境初始化之前,它为
empty 。
[[ImportMeta]]
一个对象或 empty
通过 import.meta
元属性公开的对象。在 ECMAScript 代码访问之前,它为 empty 。
[[ImportEntries]]
记录列表 或 导入条目记录
从此模块代码派生的导入条目记录的列表。
[[LocalExportEntries]]
记录列表 或 导出条目记录
从此模块代码派生的导出条目记录的列表,这些条目记录对应于模块内的声明。
[[IndirectExportEntries]]
记录列表 或 导出条目记录
从此模块代码派生的导出条目记录的列表,这些条目记录对应于模块内的重新导出或 export * as namespace
声明中的导出。
[[StarExportEntries]]
记录列表 或 导出条目记录
从此模块代码派生的导出条目记录的列表,这些条目记录对应于模块内的 export *
声明,但不包括
export * as namespace
声明。
导入条目记录 是一种 记录 ,用于提取有关单个声明性导入的信息。每个
导入条目记录 具有 表 56 中定义的字段:
表 56:导入条目记录 字段
字段名称
值类型
含义
[[ModuleRequest]]
字符串
ModuleSpecifier 的字符串值。
[[ImportName]]
字符串或 namespace-object
所需绑定由 [[ModuleRequest]] 标识的模块导出的名称。值
namespace-object 表示导入请求针对目标模块的命名空间对象。
[[LocalName]]
字符串
用于在导入模块中本地访问导入值的名称。
注1
表
57 给出了用于表示语法导入形式的导入条目记录字段示例:
表 57(信息性):导入形式映射到 导入条目记录
导入语句形式
[[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";
不创建导入条目记录。
导出条目记录 是一种 记录 ,用于提取有关单个声明性导出的信息。每个
导出条目记录 具有 表 58 中定义的字段:
表 58:导出条目记录 字段
字段名称
值类型
含义
[[ExportName]]
字符串或 null
用于模块导出此绑定的名称。
[[ModuleRequest]]
字符串或 null
ModuleSpecifier 的字符串值。如果
ExportDeclaration 没有
ModuleSpecifier ,则为
null 。
[[ImportName]]
字符串、null 、all 或
all-but-default
所需绑定由 [[ModuleRequest]] 标识的模块导出的名称。如果 ExportDeclaration 没有
ModuleSpecifier ,则为
null 。all 用于 export * as ns from "mod"
声明。all-but-default 用于 export * from "mod"
声明。
[[LocalName]]
字符串或 null
用于在导入模块中本地访问导出值的名称。如果导出值无法在模块中本地访问,则为 null 。
注2
表
59 给出了用于表示语法导出形式的导出条目记录字段示例:
表 59(信息性):导出形式映射到 导出条目记录
导出语句形式
[[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.6.1 ParseModule (sourceText , realm ,
hostDefined )
抽象操作 ParseModule 接受参数 sourceText (ECMAScript 源文本 ),realm (一个
领域记录 ),以及 hostDefined (任意)
并返回一个 源文本模块记录 或一个非空的 列表 的
SyntaxError 对象。它基于使用 Module 作为目标符号解析 sourceText
的结果创建一个 源文本模块记录 。调用时执行以下步骤:
让 body 为 ParseText (sourceText ,
Module )。
如果 body 是一个 错误列表 ,返回
body 。
让 requestedModules 为 ModuleRequests
的 body 。
让 importEntries 为 ImportEntries
的 body 。
让 importedBoundNames 为 ImportedLocalNames (importEntries )。
让 indirectExportEntries 为一个新的空 列表 。
让 localExportEntries 为一个新的空 列表 。
让 starExportEntries 为一个新的空 列表 。
让 exportEntries 为 ExportEntries
的 body 。
对 exportEntries 的每个 导出条目记录 ee ,执行以下操作
如果 ee .[[ModuleRequest]] 为 null ,则
如果 importedBoundNames 不包含 ee .[[LocalName]] ,则
将 ee 添加到 localExportEntries 。
否则
让 ie 为 importEntries 中 [[LocalName]] 是
ee .[[LocalName]] 的元素。
如果 ie .[[ImportName]] 是
namespace-object ,则
注:这是重新导入的模块命名空间对象。
将 ee 添加到 localExportEntries 。
否则
注:这是重新导入的单个名称。
将 导出条目记录 { [[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 包含
await
。
返回 源文本模块记录 { [[Realm]] : realm , [[Environment]] :
empty , [[Namespace]] : empty ,
[[CycleRoot]] : empty , [[HasTLA]] : async , [[AsyncEvaluation]] :
false , [[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.6.2 GetExportedNames ([ exportStarSet ])
源文本模块记录 module 的
GetExportedNames 具体方法接受可选参数 exportStarSet (一个 列表 的
源文本模块记录 )并返回一个 字符串列表 。调用时执行以下步骤:
断言 :module .[[Status]] 不是 new 。
如果 exportStarSet 未被传递,设置 exportStarSet 为一个新的空 列表 。
如果 exportStarSet 包含 module ,则
断言 :我们已经到达 export *
循环的起点。
返回一个新的空 列表 。
将 module 添加到 exportStarSet 。
让 exportedNames 为一个新的空 列表 。
对 module .[[LocalExportEntries]] 的每个 导出条目记录 e ,执行以下操作
断言 :module 提供此导出的直接绑定。
断言 :e .[[ExportName]] 不是 null 。
将 e .[[ExportName]] 添加到 exportedNames 。
对 module .[[IndirectExportEntries]] 的每个 导出条目记录 e ,执行以下操作
断言 :module 导入此导出的特定绑定。
断言 :e .[[ExportName]] 不是 null 。
将 e .[[ExportName]] 添加到 exportedNames 。
对 module .[[StarExportEntries]] 的每个 导出条目记录 e ,执行以下操作
断言 :e .[[ModuleRequest]] 不是 null 。
让 requestedModule 为 GetImportedModule (module ,
e .[[ModuleRequest]] )。
让 starNames 为
requestedModule .GetExportedNames(exportStarSet )。
对 starNames 的每个元素 n ,执行以下操作
如果 SameValue (n ,
"default" ) 为 false ,则
如果 exportedNames 不包含 n ,则
将 n 添加到 exportedNames 。
返回 exportedNames 。
注
GetExportedNames 不会过滤掉或抛出具有模糊星号导出绑定的名称的异常。
16.2.1.6.3 ResolveExport (exportName [, resolveSet
])
源文本模块记录 module 的
ResolveExport 具体方法接受参数 exportName (一个字符串)和可选参数 resolveSet (一个 记录 的
列表 ,字段包括 [[Module]] (一个 模块记录 )和 [[ExportName]] (一个字符串)),并返回一个 解析绑定记录 、null
或 ambiguous 。
ResolveExport 尝试将导入的绑定解析为实际定义的模块和本地绑定名称。定义模块可以是此方法所调用的 模块记录
所代表的模块,也可以是该模块导入的其他模块。参数 resolveSet 用于检测未解决的循环导入/导出路径。如果到达的特定 模块记录 和
exportName 组合已经在 resolveSet 中,则遇到导入循环。在递归调用 ResolveExport 之前,将 module 和
exportName 组合添加到 resolveSet 中。
如果找到定义模块,则返回一个 解析绑定记录 { [[Module]] , [[BindingName]]
}。此记录标识最初请求的导出的解析绑定,除非这是没有本地绑定的命名空间的导出。在这种情况下,[[BindingName]] 将设置为
namespace 。如果未找到定义或请求被发现是循环的,则返回 null 。如果请求被发现是模糊的,则返回
ambiguous 。
调用时执行以下步骤:
断言 :module .[[Status]] 不是 new 。
如果 resolveSet 未被传递,设置 resolveSet 为一个新的空 列表 。
对 resolveSet 的每个 记录 { [[Module]] , [[ExportName]] } r ,执行以下操作
如果 module 和 r .[[Module]] 是相同的 模块记录 且 SameValue (exportName ,
r .[[ExportName]] ) 为 true ,则
断言 :这是一个循环导入请求。
返回 null 。
将 记录 { [[Module]] : module , [[ExportName]] :
exportName } 添加到 resolveSet 。
对 module .[[LocalExportEntries]] 的每个 导出条目记录 e ,执行以下操作
如果 SameValue (exportName ,
e .[[ExportName]] ) 为 true ,则
断言 :module 提供此导出的直接绑定。
返回 解析绑定记录 { [[Module]] : module , [[BindingName]] : e .[[LocalName]] }。
对 module .[[IndirectExportEntries]] 的每个 导出条目记录 e ,执行以下操作
如果 SameValue (exportName ,
e .[[ExportName]] ) 为 true ,则
断言 :e .[[ModuleRequest]] 不是 null 。
让 importedModule 为 GetImportedModule (module ,
e .[[ModuleRequest]] )。
如果 e .[[ImportName]] 是 all ,则
断言 :module
不提供此导出的直接绑定。
返回 解析绑定记录 { [[Module]] : importedModule , [[BindingName]] : namespace }。
否则
断言 :module
导入此导出的特定绑定。
返回 importedModule .ResolveExport(e .[[ImportName]] , resolveSet )。
如果 SameValue (exportName ,
"default" ) 为 true ,则
断言 :module 没有明确定义
default
导出。
返回 null 。
注:default
导出不能由 export * from "mod"
声明提供。
让 starResolution 为 null 。
对 module .[[StarExportEntries]] 的每个 导出条目记录 e ,执行以下操作
断言 :e .[[ModuleRequest]] 不是 null 。
让 importedModule 为 GetImportedModule (module ,
e .[[ModuleRequest]] )。
让 resolution 为 importedModule .ResolveExport(exportName ,
resolveSet )。
如果 resolution 是 ambiguous ,返回
ambiguous 。
如果 resolution 不是 null ,则
断言 :resolution 是一个
解析绑定记录 。
如果 starResolution 是 null ,则
设置 starResolution 为 resolution 。
否则
断言 :有多个包含请求名称的 *
导入。
如果 resolution .[[Module]] 和
starResolution .[[Module]] 不是相同的 模块记录 ,返回
ambiguous 。
如果 resolution .[[BindingName]] 不是
starResolution .[[BindingName]] 且
resolution .[[BindingName]] 或
starResolution .[[BindingName]] 是
namespace ,返回 ambiguous 。
如果 resolution .[[BindingName]] 是字符串 ,starResolution .[[BindingName]] 是字符串 ,且
SameValue (resolution .[[BindingName]] , starResolution .[[BindingName]] ) 为 false ,返回
ambiguous 。
返回 starResolution 。
16.2.1.6.4 InitializeEnvironment ()
源文本模块记录 module 的
InitializeEnvironment 具体方法不接受参数,返回一个 包含
unused 的正常完成或一个 抛出完成 。调用时执行以下步骤:
对 module .[[IndirectExportEntries]] 的每个 导出条目记录 e ,执行以下操作
断言 :e .[[ExportName]] 不是 null 。
让 resolution 为 module .ResolveExport(e .[[ExportName]] )。
如果 resolution 为 null 或 ambiguous ,抛出
SyntaxError 异常。
断言 :resolution 是一个
解析绑定记录 。
断言 :module 的所有命名导出都是可解析的。
让 realm 为 module .[[Realm]] 。
断言 :realm 不是
undefined 。
让 env 为 NewModuleEnvironment (realm .[[GlobalEnv]] )。
将 module .[[Environment]] 设置为 env 。
对 module .[[ImportEntries]] 的每个 导入条目记录 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 )。
否则
执行 env .CreateImportBinding(in .[[LocalName]] , resolution .[[Module]] , resolution .[[BindingName]] )。
让 moduleContext 为一个新的 ECMAScript
代码执行上下文 。
将 moduleContext 的函数设置为 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 ,执行以下操作
如果 IsConstantDeclaration
的 d 为 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.6.5 ExecuteModule ( [ capability ] )
源文本模块记录 module 的
ExecuteModule 具体方法接受一个可选参数 capability (一个 PromiseCapability
记录 )并返回一个 包含
unused 的正常完成或一个 抛出完成 。调用时执行以下步骤:
让 moduleContext 为一个新的 ECMAScript
代码执行上下文 。
将 moduleContext 的函数设置为 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 (Evaluation of module .[[ECMAScriptCode]] )。
暂停 moduleContext 并将其从 执行上下文堆栈 中移除。
恢复现在位于 执行上下文堆栈 顶部的上下文作为
运行的执行上下文 。
如果 result 是一个 中止完成 ,则
返回 ? result 。
否则
断言 :capability 是一个
PromiseCapability
记录 。
执行 AsyncBlockStart (capability ,
module .[[ECMAScriptCode]] , moduleContext )。
返回 unused 。
16.2.1.7 GetImportedModule (referrer , specifier )
抽象操作 GetImportedModule 接受参数 referrer (一个 循环模块记录 )和
specifier (一个字符串),返回一个 模块记录 。调用时执行以下步骤:
断言 :referrer .[[LoadedModules]] 中恰好有一个元素是 记录 ,其 [[Specifier]] 是 specifier ,因为在调用此抽象操作之前,referrer 上的
LoadRequestedModules 已成功完成。
令 record 为 referrer .[[LoadedModules]] 中 [[Specifier]] 为 specifier 的 记录 。
返回 record .[[Module]] 。
16.2.1.8 HostLoadImportedModule (referrer , specifier ,
hostDefined , payload )
宿主定义 的抽象操作 HostLoadImportedModule 接受参数
referrer (一个 脚本记录 、一个 循环模块记录 或一个 Realm
记录 ),specifier (一个字符串)、hostDefined (任何类型)和 payload (一个
GraphLoadingState 记录 或一个
PromiseCapability
记录 ),并返回 unused 。
注
一个 referrer 可以是 Realm 记录 的示例是在 Web 浏览器 宿主 中。如果用户点击给出的控件
<button type ="button" onclick ="import('./foo.mjs')" > Click me</button >
在 import()
表达式运行时,不会有
活动脚本或模块 。更普遍地说,这种情况发生在任何
宿主 将
执行上下文 推到 执行上下文堆栈 ,并且它们的
ScriptOrModule 组件为 null 的任何情况下。
HostLoadImportedModule 的实现必须符合以下要求:
宿主环境 必须执行 FinishLoadingImportedModule (referrer ,
specifier , payload , result ),其中 result 是一个 包含 已加载
模块记录 的正常完成或一个 抛出完成 ,无论是同步或异步。
如果多次使用相同的 (referrer , specifier ) 对调用此操作,并且它执行 FinishLoadingImportedModule (referrer ,
specifier , payload , result ),其中 result 是一个 正常完成 ,则它必须每次都使用相同的
result 执行 FinishLoadingImportedModule (referrer ,
specifier , payload , result )。
操作必须将 payload 视为一个不透明值,并将其传递给 FinishLoadingImportedModule 。
实际执行的过程是 宿主定义 的,但通常包括执行加载适当的 模块记录 所需的任何 I/O 操作。多个不同的
(referrer , specifier ) 对可能映射到相同的 模块记录
实例。实际的映射语义是 宿主定义 的,但通常在映射过程中会对 specifier
进行规范化处理。一个典型的规范化过程包括扩展相对和缩写的路径说明符等操作。
16.2.1.9 FinishLoadingImportedModule (referrer ,
specifier , payload , result )
抽象操作 FinishLoadingImportedModule 接受参数 referrer (一个 脚本记录 、一个 循环模块记录 或一个 Realm
记录 ),specifier (一个字符串)、payload (一个 GraphLoadingState 记录 或一个
PromiseCapability 记录 ),以及
result (一个 包含 一个
模块记录 的正常完成或一个 抛出完成 )并返回
unused 。调用时执行以下步骤:
1. 如果 result 是一个 正常完成 ,则
a. 如果 referrer .[[LoadedModules]] 包含一个 记录 ,其
[[Specifier]] 为 specifier ,则
i. 断言 :该 记录
的 [[Module]] 是 result .[[Value]] 。
b. 否则,
i. 将 { [[Specifier]] :
specifier , [[Module]] : result .[[Value]] } 记录附加到 referrer .[[LoadedModules]] 。
2. 如果 payload 是一个 GraphLoadingState 记录 ,则
a. 执行 ContinueModuleLoading (payload ,
result )。
3. 否则,
a. 执行 ContinueDynamicImport (payload ,
result )。
4. 返回 unused 。
16.2.1.10 GetModuleNamespace ( module )
抽象操作 GetModuleNamespace 接受参数 module (模块记录
的具体子类的实例)并返回一个模块命名空间对象或 empty 。它检索表示 module 的导出的模块命名空间对象,首次请求时懒加载创建,并存储在
module .[[Namespace]] 中以供将来检索。调用时执行以下步骤:
1. 断言 :如果 module 是一个 循环模块记录 ,则
module .[[Status]] 不是 new 或
unlinked 。
2. 让 namespace 为 module .[[Namespace]] 。
3. 如果 namespace 是 empty ,则
a. 让 exportedNames 为
module .GetExportedNames()。
b. 让 unambiguousNames 为一个新的空 列表 。
c. 对 exportedNames 的每个元素 name ,执行以下步骤:
i. 让 resolution 为
module .ResolveExport(name )。
ii. 如果 resolution 是一个 ResolvedBinding
记录 ,则将 name 添加到 unambiguousNames 。
d. 将 namespace 设置为 ModuleNamespaceCreate (module ,
unambiguousNames )。
4. 返回 namespace 。
注
GetModuleNamespace 永远不会抛出错误。相反,此时未解析的名称仅会被排除在命名空间之外。除非它们全部是未明确请求的模糊星号导出,否则它们稍后将导致实际的链接错误。
16.2.1.11 运行时语义:求值
Module :
[empty]
1. 返回 undefined 。
ModuleBody :
ModuleItemList
1. 令 result 为 Completion (Evaluation of ModuleItemList )。
2. 如果 result 是 正常完成 并且
result .[[Value]] 是 empty ,则
a. 返回 undefined 。
3. 返回 ? result 。
ModuleItemList
:
ModuleItemList
ModuleItem
1. 令 sl 为 ? Evaluation of ModuleItemList 。
2. 令 s 为 Completion (Evaluation of ModuleItem )。
3. 返回 ? UpdateEmpty (s ,
sl )。
注
ModuleItem :
ImportDeclaration
1. 返回 empty 。
16.2.2 导入
语法
ImportDeclaration
:
import
ImportClause
FromClause
;
import
ModuleSpecifier
;
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]
16.2.2.1 静态语义:早期错误
ModuleItem :
ImportDeclaration
16.2.2.2 静态语义:ImportEntries
语法指示操作
ImportEntries 不带参数并返回一个 列表
的 ImportEntry 记录 。它在以下各个生成式上逐步定义:
Module :
[empty]
1. 返回一个新的空 列表 。
ModuleItemList
:
ModuleItemList
ModuleItem
1. 令 entries1 为 ImportEntries
的 ModuleItemList 。
2. 令 entries2 为 ImportEntries
的 ModuleItem 。
3. 返回 list-concatenation 的
entries1 和 entries2 。
ModuleItem :
ExportDeclaration
StatementListItem
1. 返回一个新的空 列表 。
ImportDeclaration
:
import
ImportClause
FromClause
;
1. 令 module 为 ModuleRequests
的 FromClause
的唯一元素。
2. 返回 ImportEntriesForModule
的 ImportClause 和参数
module 。
ImportDeclaration
:
import
ModuleSpecifier
;
1. 返回一个新的空 列表 。
16.2.2.3 静态语义:ImportEntriesForModule
语法指示操作
ImportEntriesForModule 采用参数 module (一个字符串) 并返回一个 列表
的 ImportEntry 记录 。它在以下各个生成式上逐步定义:
ImportClause
:
ImportedDefaultBinding
,
NameSpaceImport
1. 令 entries1 为 ImportEntriesForModule
的 ImportedDefaultBinding
和参数 module 。
2. 令 entries2 为 ImportEntriesForModule
的 NameSpaceImport 和参数
module 。
3. 返回 list-concatenation 的
entries1 和 entries2 。
ImportClause
:
ImportedDefaultBinding
,
NamedImports
1. 令 entries1 为 ImportEntriesForModule
的 ImportedDefaultBinding
和参数 module 。
2. 令 entries2 为 ImportEntriesForModule
的 NamedImports 和参数
module 。
3. 返回 list-concatenation 的
entries1 和 entries2 。
ImportedDefaultBinding
:
ImportedBinding
1. 令 localName 为 BoundNames
的 ImportedBinding 的唯一元素。
2. 令 defaultEntry 为 ImportEntry 记录
{ [[ModuleRequest]] : module , [[ImportName]] : "default" ,
[[LocalName]] : localName }。
3. 返回 « defaultEntry »。
NameSpaceImport
:
*
as
ImportedBinding
1. 令 localName 为 StringValue
的 ImportedBinding 。
2. 令 entry 为 ImportEntry 记录
{ [[ModuleRequest]] : module , [[ImportName]] : namespace-object ,
[[LocalName]] : localName }。
3. 返回 « entry »。
NamedImports
:
{
}
1. 返回一个新的空 列表 。
ImportsList
:
ImportsList
,
ImportSpecifier
1. 令 specs1 为 ImportEntriesForModule
的 ImportsList 和参数 module 。
2. 令 specs2 为 ImportEntriesForModule
的 ImportSpecifier 和参数
module 。
3. 返回 list-concatenation 的
specs1 和 specs2 。
ImportSpecifier
:
ImportedBinding
1. 令 localName 为 BoundNames
的 ImportedBinding 的唯一元素。
2. 令 entry 为 ImportEntry 记录
{ [[ModuleRequest]] : module , [[ImportName]] : localName ,
[[LocalName]] : localName }。
3. 返回 « entry »。
ImportSpecifier
:
ModuleExportName
as
ImportedBinding
1. 令 importName 为 StringValue
的 ModuleExportName 。
2. 令 localName 为 StringValue
的 ImportedBinding 。
3. 令 entry 为 ImportEntry 记录
{ [[ModuleRequest]] : module , [[ImportName]] : importName ,
[[LocalName]] : localName }。
4. 返回 « entry »。
16.2.3 导出
语法
ExportDeclaration(导出声明)
:
export
ExportFromClause(从子句导出)
FromClause(来自子句)
;
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
不接受任何参数,并返回一个 字符串列表 。
注
导出绑定是与模块的 模块 的
导出名称
显式关联的本地绑定名称。
它分散定义在以下产生式中:
ModuleItemList
:
ModuleItemList
ModuleItem
1. 令 names1 为 ExportedBindings
of ModuleItemList 。
2. 令 names2 为 ExportedBindings
of ModuleItem 。
3. 返回 list-concatenation of
names1 和 names2 。
ModuleItem
:
ImportDeclaration
StatementListItem
1. 返回一个新的空列表 。
ExportDeclaration
:
export
ExportFromClause
FromClause
;
1. 返回一个新的空列表 。
ExportDeclaration
:
export
NamedExports
;
1. 返回 ExportedBindings
of NamedExports 。
ExportDeclaration
:
export
VariableStatement
1. 返回 BoundNames of
VariableStatement 。
ExportDeclaration
:
export
Declaration
1. 返回 BoundNames of
Declaration 。
ExportDeclaration
:
export
default
HoistableDeclaration
export
default
ClassDeclaration
export
default
AssignmentExpression
;
1. 返回 BoundNames of
this ExportDeclaration 。
NamedExports
:
{
}
1. 返回一个新的空列表 。
ExportsList
:
ExportsList
,
ExportSpecifier
1. 令 names1 为 ExportedBindings
of ExportsList 。
2. 令 names2 为 ExportedBindings
of ExportSpecifier 。
3. 返回 list-concatenation of
names1 和 names2 。
ExportSpecifier
: ModuleExportName
1. 返回一个 列表 ,其唯一元素是第一个ModuleExportName 的 StringValue 。
ExportSpecifier
:
ModuleExportName
as
ModuleExportName
1. 返回一个 列表 ,其唯一元素是第一个ModuleExportName 的 StringValue 。
16.2.3.3 静态语义:ExportedNames
语法导向操作
ExportedNames 不接受任何参数,返回一个
列表
的字符串。
注
ExportedNames 是模块显式映射到其本地名称绑定的外部可见名称。
它分段定义如下:
ModuleItemList
:
ModuleItemList
ModuleItem
1.
令 names1 为
ExportedNames
of
ModuleItemList
。
2.
令 names2 为
ExportedNames
of
ModuleItem
。
3.
返回
列表连接
的 names1 和 names2 。
ModuleItem
:
ExportDeclaration
1.
返回
ExportedNames
of
ExportDeclaration
。
ModuleItem
:
ImportDeclaration
StatementListItem
1.
返回一个新的空
列表
。
ExportDeclaration
:
export
ExportFromClause
FromClause
;
1.
返回
ExportedNames
of
ExportFromClause
。
ExportFromClause
:
*
1.
返回一个新的空
列表
。
ExportFromClause
:
*
as
ModuleExportName
1.
返回一个
列表
,其唯一元素是
StringValue
of
ModuleExportName
。
ExportFromClause
:
NamedExports
1.
返回
ExportedNames
of
NamedExports
。
ExportDeclaration
:
export
VariableStatement
1.
返回
BoundNames
of
VariableStatement
。
ExportDeclaration
:
export
Declaration
1.
返回
BoundNames
of
Declaration
。
ExportDeclaration
:
export
default
HoistableDeclaration
export
default
ClassDeclaration
export
default
AssignmentExpression
;
1.
返回 «
"default"
»。
NamedExports
:
{
}
1.
返回一个新的空
列表
。
ExportsList
:
ExportsList
,
ExportSpecifier
1.
令 names1 为
ExportedNames
of
ExportsList
。
2.
令 names2 为
ExportedNames
of
ExportSpecifier
。
3.
返回
列表连接
的 names1 和 names2 。
ExportSpecifier
:
ModuleExportName
1.
返回一个
列表
,其唯一元素是
StringValue
of
ModuleExportName
。
ExportSpecifier
:
ModuleExportName
as
ModuleExportName
1.
返回一个
列表
,其唯一元素是
StringValue
of the second
ModuleExportName
。
16.2.3.4 静态语义: ExportEntries
语法导向操作
ExportEntries 不接受任何参数,并返回一个
列表
,其元素是
ExportEntry 记录
。它按以下各个产生式定义:
Module
:
[empty]
1.
返回一个新的空
列表
。
ModuleItemList
:
ModuleItemList
ModuleItem
1.
令 entries1 为
ExportEntries
of
ModuleItemList
。
2.
令 entries2 为
ExportEntries
of
ModuleItem
。
3.
返回 entries1 和 entries2 的
列表连接
。
ModuleItem
:
ImportDeclaration
StatementListItem
1.
返回一个新的空
列表
。
ExportDeclaration
:
export
ExportFromClause
FromClause
;
1.
令 module 为
ModuleRequests
of
FromClause
的唯一元素。
2.
返回
ExportEntriesForModule
of
ExportFromClause
并带参数 module 。
ExportDeclaration
:
export
NamedExports
;
1.
返回
ExportEntriesForModule
of
NamedExports
并带参数
null 。
ExportDeclaration
:
export
VariableStatement
1.
令 entries 为一个新的空
列表
。
2.
令 names 为
BoundNames
of
VariableStatement
。
3.
对 names 中的每个元素 name ,执行
a.
将
ExportEntry 记录
{ [[ModuleRequest]] :
null ,
[[ImportName]] : null ,
[[LocalName]] : name ,
[[ExportName]] : name } 附加到 entries 。
4.
返回 entries 。
ExportDeclaration
:
export
Declaration
1.
令 entries 为一个新的空
列表
。
2.
令 names 为
BoundNames
of
Declaration
。
3.
对 names 中的每个元素 name ,执行
a.
将
ExportEntry 记录
{ [[ModuleRequest]] :
null ,
[[ImportName]] : null ,
[[LocalName]] : name ,
[[ExportName]] : name } 附加到 entries 。
4.
返回 entries 。
ExportDeclaration
:
export
default
HoistableDeclaration
1.
令 names 为
BoundNames
of
HoistableDeclaration
。
2.
令 localName 为 names 的唯一元素。
3.
返回一个
列表
,其唯一元素是一个新的
ExportEntry 记录
{ [[ModuleRequest]] :
null ,
[[ImportName]] : null ,
[[LocalName]] : localName ,
[[ExportName]] :
"default" }。
ExportDeclaration
:
export
default
ClassDeclaration
1.
令 names 为
BoundNames
of
ClassDeclaration
。
2.
令 localName 为 names 的唯一元素。
3.
返回一个
列表
,其唯一元素是一个新的
ExportEntry 记录
{ [[ModuleRequest]] :
null ,
[[ImportName]] : null ,
[[LocalName]] : localName ,
[[ExportName]] :
"default" }。
ExportDeclaration
:
export
default
AssignmentExpression
;
1.
令 entry 为
ExportEntry 记录
{ [[ModuleRequest]] :
null ,
[[ImportName]] : null ,
[[LocalName]] :
"*default*" ,
[[ExportName]] :
"default" }。
2.
返回 « entry »。
注
"*default*" 在本规范中用作匿名默认导出值的合成名称。
有关详细信息,请参见
此注释
。
16.2.3.5 静态语义:ExportEntriesForModule
语法导向操作
ExportEntriesForModule 接受参数 module (一个字符串或
null )并返回一个
列表
,其中包含
ExportEntry 记录
。它在以下生成式上逐一定义:
ExportFromClause
:
*
1.
令 entry 为
ExportEntry 记录
{ [[ModuleRequest]] :
module , [[ImportName]] :
all-but-default , [[LocalName]] :
null , [[ExportName]] :
null }.
2. 返回 « entry »。
ExportFromClause
:
*
as
ModuleExportName
1. 令 exportName 为
StringValue
of
ModuleExportName
.
2. 令 entry 为
ExportEntry 记录
{ [[ModuleRequest]] :
module , [[ImportName]] :
all , [[LocalName]] :
null , [[ExportName]] :
exportName }.
3. 返回 « entry »。
NamedExports
:
{
}
1. 返回一个新的空
列表
。
ExportsList
:
ExportsList
,
ExportSpecifier
1. 令 specs1 为
ExportEntriesForModule
of
ExportsList
with argument module 。
2. 令 specs2 为
ExportEntriesForModule
of
ExportSpecifier
with argument module 。
3. 返回
list-concatenation
of specs1 and specs2 。
ExportSpecifier
:
ModuleExportName
1. 令 sourceName 为
StringValue
of
ModuleExportName
。
2. 如果 module 是
null ,则
a. 令 localName 为
sourceName 。
b. 令 importName 为
null 。
3. 否则,
a. 令 localName 为
null 。
b. 令 importName 为
sourceName 。
4. 返回一个
列表
,其唯一元素是一个新的
ExportEntry 记录
{ [[ModuleRequest]] :
module , [[ImportName]] :
importName , [[LocalName]] :
localName , [[ExportName]] :
sourceName }。
ExportSpecifier
:
ModuleExportName
as
ModuleExportName
1. 令 sourceName 为
StringValue
of the first
ModuleExportName
。
2. 令 exportName 为
StringValue
of the second
ModuleExportName
。
3. 如果 module 是
null ,则
a. 令 localName 为
sourceName 。
b. 令 importName 为
null 。
4. 否则,
a. 令 localName 为
null 。
b. 令 importName 为
sourceName 。
5. 返回一个
列表
,其唯一元素是一个新的
ExportEntry 记录
{ [[ModuleRequest]] :
module , [[ImportName]] :
importName , [[LocalName]] :
localName , [[ExportName]] :
exportName }。
16.2.3.6 静态语义:ReferencedBindings
语法导向操作
ReferencedBindings 不接受任何参数,返回一个
列表
,其中包含
解析节点
。它在以下生成式上逐一定义:
NamedExports
:
{
}
1.
返回一个新的空
列表
。
ExportsList
:
ExportsList
,
ExportSpecifier
1.
令 names1 为
ReferencedBindings
of
ExportsList
。
2.
令 names2 为
ReferencedBindings
of
ExportSpecifier
。
3.
返回 names1 和 names2 的
列表连接
。
ExportSpecifier
:
ModuleExportName
as
ModuleExportName
1.
返回
ReferencedBindings
of the first
ModuleExportName
。
ModuleExportName
:
IdentifierName
1.
返回一个
列表
,其唯一元素是
IdentifierName
。
ModuleExportName
:
StringLiteral
1.
返回一个
列表
,其唯一元素是
StringLiteral
。
16.2.3.7 运行时语义:Evaluation
ExportDeclaration
:
export
ExportFromClause
FromClause
;
export
NamedExports
;
1. 返回empty 。
ExportDeclaration
:
export
VariableStatement
1. 返回 ?
Evaluation
of
VariableStatement
。
ExportDeclaration
:
export
Declaration
1. 返回 ?
Evaluation
of
Declaration
。
ExportDeclaration
:
export
default
HoistableDeclaration
1. 返回 ?
Evaluation
of
HoistableDeclaration
。
ExportDeclaration
:
export
default
ClassDeclaration
1. 令 value 为 ?
BindingClassDeclarationEvaluation
of
ClassDeclaration
。
2. 令 className 为
BoundNames
的唯一元素 of
ClassDeclaration
。
3. 如果 className 是 "*default*" ,则
a. 令 env 为
运行时执行上下文
的 LexicalEnvironment。
b. 执行 ?
InitializeBoundName
("*default*" ,value ,env )。
4. 返回 empty 。
ExportDeclaration
:
export
default
AssignmentExpression
;
1. 如果
IsAnonymousFunctionDefinition
(
AssignmentExpression
) 是 true ,则
a. 令 value 为 ?
NamedEvaluation
of
AssignmentExpression
,参数为 "default" 。
2. 否则,
a. 令 rhs 为 ?
Evaluation
of
AssignmentExpression
。
b. 令 value 为 ?
GetValue
(rhs )。
3. 令 env 为
运行时执行上下文
的 LexicalEnvironment。
4. 执行 ?
InitializeBoundName
("*default*" ,value ,env )。
5. 返回 empty 。
17 错误处理和语言扩展
实现必须在评估相关 ECMAScript 语言结构时报告大多数错误。提前错误
是在评估包含错误的 脚本
中的任何结构之前即可检测和报告的错误。提前错误 的存在会阻止结构的评估。实现必须在解析 脚本 的过程中报告 提前错误 。提前错误 在 eval 代码中会在调用
eval
时报告,并阻止 eval 代码的评估。所有不是 提前错误 的错误都是运行时错误。
实现必须将规范中“静态语义:提前错误”子条款中列出的任何情况报告为 提前错误 。
实现不得将其他类型的错误视为 提前错误 ,即使编译器可以证明在任何情况下某个结构都无法执行而不出错。在这种情况下,实施可能会发出提前警告,但不应在实际执行相关结构之前报告错误。
实现必须按规定报告所有错误,但以下情况除外:
除 17.1 限制外,宿主 或实现可以扩展 脚本 语法、模块 语法和正则表达式模式或标志语法。为了允许这样做,所有可能抛出
SyntaxError 的操作(例如调用 eval
、使用正则表达式字面量或使用 Function 或 RegExp 构造函数 )在遇到
宿主定义 的扩展脚本语法或正则表达式模式或标志语法时,可以表现出 宿主定义
的行为,而不是抛出 SyntaxError 。
除 17.1 限制外,宿主
或实现可以提供规范中未描述的其他类型、值、对象、属性和函数。这可能会导致某些结构(例如在全局范围内查找变量)表现出 宿主定义 的行为,而不是抛出错误(例如
ReferenceError )。
17.1 禁止的扩展
实现不得以下列方式扩展此规范:
18 ECMAScript 标准内置对象
在 ECMAScript 脚本 或 模块 开始执行时,有一些内置对象是可用的。其中一个是
全局对象 ,它是正在执行的程序的全局环境的一部分。其他对象可以作为 全局对象 的初始属性或间接作为可访问内置对象的属性进行访问。
除非另有说明,否则可作为函数调用的内置对象是具有 10.3 中描述的特性的内置 函数对象 。除非另有说明,内置对象的 [[Extensible]] 内部槽的初始值为 true 。每个内置 函数对象 都有一个 [[Realm]] 内部槽,其值是对象最初创建时的 Realm 记录 中的 realm 。
许多内置对象是函数:它们可以用参数调用。其中一些还是 构造函数 :它们是打算与 new
运算符一起使用的函数。对于每个内置函数,本规范描述了该函数所需的参数以及该 函数对象 的属性。对于每个内置 构造函数 ,本规范还描述了该 构造函数 的原型对象的属性以及通过调用该 构造函数 的
new
表达式返回的特定对象实例的属性。
除非在特定函数的描述中另有说明,否则如果内置函数或 构造函数 给出的参数少于该函数指定的要求,则该函数或 构造函数
应表现得完全像给出了足够的附加参数一样,每个这样的参数都是 undefined
值。这些缺失的参数被视为“不存在”,并可以通过规范算法以这种方式识别。在特定函数的描述中,术语“this 值”和“NewTarget”具有 10.3 中给出的含义。
除非在特定函数的描述中另有说明,否则如果内置函数或 构造函数
给出的参数多于该函数指定的允许数量,则多余的参数由调用评估,然后被函数忽略。但是,实施可以定义与此类参数相关的实施特定行为,只要该行为不是简单地基于存在额外参数而抛出的
TypeError 异常。
注 1
添加额外功能到内置函数集合的实现建议通过添加新函数而不是向现有函数添加新参数来实现。
除非另有说明,每个内置函数和每个内置 构造函数 的 [[Prototype]]
内部槽的值都是 Function.prototype
对象 ,这是表达式 Function.prototype
(20.2.3 )的初始值。
除非另有说明,每个内置原型对象的 [[Prototype]] 内部槽的值都是 Object.prototype
对象 ,这是表达式 Object.prototype
(20.1.3 )的初始值,但
Object.prototype
对象 本身除外。
如果本规范通过算法步骤定义了内置 构造函数 的行为,则该行为适用于 [[Call]] 和 [[Construct]] 。如果这样的算法需要区分这两种情况,它会检查 NewTarget 是否为
undefined ,这表示 [[Call]] 调用。
未标识为 构造函数 的内置 函数对象 除非在特定函数的描述中另有说明,否则不会实现
[[Construct]] 内部方法。
未标识为 构造函数 的内置 函数对象 除非在特定函数的描述中另有说明,否则没有
"prototype" 属性。
本规范中定义的每个内置函数都是通过调用 CreateBuiltinFunction
抽象操作创建的(10.3.4 )。length 和
name 参数的值是 "length" 和 "name" 属性的初始值,如下所述。prefix
参数的值也类似讨论。
每个内置 函数对象 ,包括 构造函数 ,都有一个
"length" 属性,其值是一个非负的 整数 。除非另有说明,此值是函数描述的小节标题中显示的必需参数的数量。可选参数和剩余参数不包含在参数计数中。
注 2
例如,函数对象 的初始值为 "map" 属性的
Array 原型对象
描述在小节标题«Array.prototype.map (callbackFn [ , thisArg])»下,其中显示了两个命名参数 callbackFn 和 thisArg,后者是可选的;因此,该
函数对象 的 "length" 属性的值为
1 𝔽 。
除非另有说明,内置 函数对象 的 "length"
属性具有以下属性:{ [[Writable]] :false ,[[Enumerable]] :false ,[[Configurable]] :true }。
每个内置 函数对象 ,包括 构造函数 ,都有一个
"name" 属性,其值 是一个字符串 。除非另有说明,此值是本规范中给定的函数的名称。标识为匿名函数的函数使用空字符串作为
"name" 属性的值。对于指定为对象属性的函数,名称值是用于访问该函数的 属性名称 字符串。指定为内置属性的 get 或 set 访问器函数的函数在调用
CreateBuiltinFunction 时,将
"get" 或 "set" (分别)传递给 prefix 参数。
为每个内置函数明确指定的 "name" 属性的值是其 属性键 是一个符号
值。如果这样的明确指定的值以前缀 "get " 或 "set " 开头,并且为其指定的函数是内置属性的 get 或 set
访问器函数,则指定的值将前缀删除并传递给 name 参数,而值 "get" 或 "set" (分别)传递给
prefix 参数在调用 CreateBuiltinFunction 时。
除非另有说明,内置 函数对象 的 "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
全局对象 中"globalThis" 属性的初始值在Realm
Record realm 中为realm .[[GlobalEnv]] .[[GlobalThisValue]] 。
此属性的特性为 { [[Writable]] : true , [[Enumerable]] : false , [[Configurable]] :
true }。
19.1.2 Infinity
Infinity
的值为+∞ 𝔽 (见6.1.6.1 )。此属性的特性为
{ [[Writable]] : false , [[Enumerable]] :
false , [[Configurable]] : false }。
19.1.3 NaN
NaN
的值为NaN (见6.1.6.1 )。此属性的特性为
{ [[Writable]] : false , [[Enumerable]] :
false , [[Configurable]] : false }。
19.1.4 undefined
undefined
的值为undefined (见6.1.1 )。此属性的特性为
{ [[Writable]] : false , [[Enumerable]] :
false , [[Configurable]] : false }。
19.2 全局对象的函数属性
19.2.1 eval ( x )
此函数是 %eval% 内置对象。
调用时执行以下步骤:
1. 返回 ? PerformEval (x , false ,
false )。
19.2.1.1 PerformEval ( x , strictCaller ,
direct )
抽象操作 PerformEval 接受参数 x (一个 ECMAScript
语言值 )、strictCaller (一个布尔值),和 direct (一个布尔值),返回一个 正常完成包含的
ECMAScript 语言值 或 抛出完成 。调用时执行以下步骤:
1. 断言 :如果 direct 是
false ,则 strictCaller 也是 false 。
2. 如果 x 不是字符串 ,返回
x 。
3. 令 evalRealm 为 当前 Realm 记录 。
4. 注意:在 直接
eval 的情况下,evalRealm 是调用 eval
和 eval
函数本身的
realm 。
5. 执行 ? HostEnsureCanCompileStrings (evalRealm ,
« », x , direct )。
6. 令 inFunction 为 false 。
7. 令 inMethod 为 false 。
8. 令 inDerivedConstructor 为
false 。
9. 令 inClassFieldInitializer 为
false 。
10. 如果 direct 是 true ,则
a. 令 thisEnvRec 为 GetThisEnvironment ()。
b. 如果 thisEnvRec 是 函数环境记录 ,则
i. 令 F 为 thisEnvRec .[[FunctionObject]] 。
ii. 将 inFunction 设为
true 。
iii. 将 inMethod 设为
thisEnvRec .HasSuperBinding()。
iv. 如果 F .[[ConstructorKind]] 是 derived ,则将
inDerivedConstructor 设为 true 。
v. 令 classFieldInitializerName 为
F .[[ClassFieldInitializerName]] 。
vi. 如果 classFieldInitializerName 不是
empty ,则将 inClassFieldInitializer 设为
true 。
11. 按 实现定义 的顺序执行以下子步骤,可能会交错解析和错误检测:
a. 令 script 为 ParseText (StringToCodePoints (x ),
Script )。
b. 如果 script 是一个包含错误的 列表 ,抛出一个
SyntaxError 异常。
c. 如果 script 不包含 ScriptBody ,返回
undefined 。
d. 令 body 为 script 的 ScriptBody 。
e. 如果 inFunction 为 false 并且
body 包含 NewTarget ,抛出一个
SyntaxError 异常。
f. 如果 inMethod 为 false 并且
body 包含 SuperProperty ,抛出一个
SyntaxError 异常。
g. 如果 inDerivedConstructor 为 false
并且 body 包含 SuperCall ,抛出一个
SyntaxError 异常。
h. 如果 inClassFieldInitializer 为 true
并且 ContainsArguments
的 body 是 true ,抛出一个 SyntaxError 异常。
12. 如果 strictCaller 是 true ,令
strictEval 为 true 。
13. 否则,令 strictEval 为 IsStrict 的
script 。
14. 令 runningContext 为 正在运行的执行上下文 。
15. 注意:如果 direct 是 true ,则
runningContext 将是执行 直接
eval 的 执行上下文 。如果 direct 是
false ,runningContext 将是调用 eval
函数的 执行上下文 。
16. 如果 direct 是 true ,则
a. 令 lexEnv 为 NewDeclarativeEnvironment (runningContext
的词法环境)。
b. 令 varEnv 为 runningContext 的变量环境。
c. 令 privateEnv 为 runningContext 的私有环境。
17. 否则,
a. 令 lexEnv 为 NewDeclarativeEnvironment (evalRealm
的 [[GlobalEnv]] )。
b. 令 varEnv 为 evalRealm 的 [[GlobalEnv]] 。
c. 令 privateEnv 为 null 。
18. 如果 strictEval 是 true ,将
varEnv 设为 lexEnv 。
19. 如果 runningContext 尚未暂停,暂停 runningContext 。
20. 令 evalContext 为一个新的 ECMAScript
代码执行上下文 。
21. 将 evalContext 的函数设为 null 。
22. 将 evalContext 的 Realm 设为 evalRealm 。
23. 将 evalContext 的脚本或模块设为 runningContext
的脚本或模块。
24. 将 evalContext 的变量环境设为 varEnv 。
25. 将 evalContext 的词法环境设为 lexEnv 。
26. 将 evalContext 的私有环境设为 privateEnv 。
27. 将 evalContext 推入 执行上下文堆栈 ;evalContext
现在是 正在运行的执行上下文 。
28. 令 result 为 Completion (EvalDeclarationInstantiation (body ,
varEnv , lexEnv , privateEnv , strictEval ))。
29. 如果 result 是 正常完成 ,则
a. 将 result 设为 Completion (Evaluation 的 body )。
30. 如果 result 是 正常完成 并且
result .[[Value]] 是
empty ,则
a. 将 result 设为 NormalCompletion (undefined )。
31. 暂停 evalContext 并将其从 执行上下文堆栈 中移除。
32. 恢复现在在 执行上下文堆栈 顶部的上下文作为 正在运行的执行上下文 。
33. 返回 ? result 。
注
如果调用上下文的代码或 eval 代码是 严格模式代码 ,则 eval
代码不能在调用上下文的变量环境中实例化变量或函数绑定。而是将这些绑定实例化在一个仅对 eval 代码可访问的新变量环境中。由 let
、const
或
class
声明引入的绑定始终在新的词法环境中实例化。
19.2.1.2 HostEnsureCanCompileStrings ( calleeRealm ,
parameterStrings , bodyString , direct )
HostEnsureCanCompileStrings 是一个 host-defined 抽象操作,接收参数
calleeRealm (一个 Realm
Record )、parameterStrings (一个字符串的 列表 )、bodyString (一个字符串),以及
direct (一个布尔值),返回一个 正常完成记录 (包含
unused )或一个 抛出完成记录 。它允许
宿主环境 阻止某些 ECMAScript
函数,这些函数允许开发者将字符串解释并评估为 ECMAScript 代码。
parameterStrings 表示在使用某个函数 构造函数
时,将连接在一起以构建参数列表的字符串。bodyString 表示函数体或传递给 eval
调用的字符串。direct 表示评估是否为
直接 eval 。
HostEnsureCanCompileStrings 的默认实现是返回 NormalCompletion (unused )。
19.2.1.3 EvalDeclarationInstantiation ( body , varEnv ,
lexEnv , privateEnv , strict )
抽象操作 EvalDeclarationInstantiation 接收参数 body (一个 ScriptBody 解析节点 )、varEnv (一个
环境记录 )、lexEnv (一个
声明性环境记录 )、privateEnv (一个
私有环境记录 或
null ),以及 strict (一个布尔值),并返回一个 正常完成记录 (包含
unused )或一个 抛出完成记录 。它执行以下步骤:
1. 令 varNames 为 body 的 VarDeclaredNames 。
2. 令 varDeclarations 为 body 的 VarScopedDeclarations 。
3. 如果 strict 为 false ,则:
a. 如果 varEnv 是一个 全局环境记录 ,则:
i. 对于 varNames 中的每个元素 name ,执行:
1. 如果
varEnv .HasLexicalDeclaration(name ) 为 true ,则抛出一个
SyntaxError 异常。
2. 注意:eval
不会创建一个会被全局词法声明遮蔽的全局 var 声明。
b. 令 thisEnv 为 lexEnv 。
c. 断言 :以下循环将会终止。
d. 重复,直到 thisEnv 不再是 varEnv :
i. 如果 thisEnv 不是一个对象
环境记录 ,则:
1. 注意:with 语句的环境不能包含任何词法声明,所以不需要检查 var/let 提升冲突。
2. 对于 varNames 中的每个元素 name ,执行:
a. 如果
! thisEnv .HasBinding(name ) 为 true ,则:
i. 抛出一个 SyntaxError 异常。
ii. 注意:附录 B.3.4
定义了上述步骤的替代语义。
b. 注意:直接
eval 不会提升 var 声明覆盖同名词法声明。
ii. 将 thisEnv 设置为 thisEnv 的 [[OuterEnv]] 。
4. 令 privateIdentifiers 为一个新的空 列表 。
5. 令 pointer 为 privateEnv 。
6. 重复,直到 pointer 为 null :
a. 对于 pointer 的 [[Names]] 中的每个
私有名称 binding ,执行:
i. 如果 privateIdentifiers 不包含 binding 的
[[Description]] ,则将 binding 的 [[Description]] 添加到 privateIdentifiers 。
b. 将 pointer 设置为 pointer 的 [[OuterPrivateEnvironment]] 。
7. 如果 body 的 AllPrivateIdentifiersValid
的参数为 privateIdentifiers 为 false ,则抛出一个 SyntaxError 异常。
8. 令 functionsToInitialize 为一个新的空 列表 。
9. 令 declaredFunctionNames 为一个新的空 列表 。
10. 对于 varDeclarations 中的每个元素 d ,按逆序(列表 顺序),执行:
a. 如果 d 不是 VariableDeclaration 、ForBinding 或
BindingIdentifier ,则:
i. 断言 :d 是 FunctionDeclaration 、GeneratorDeclaration 、AsyncFunctionDeclaration
或 AsyncGeneratorDeclaration 。
ii. 注意:如果有多个同名的函数声明,使用最后一个声明。
iii. 令 fn 为 d 的 BoundNames
的唯一元素。
iv. 如果 declaredFunctionNames 不包含 fn ,则:
1. 如果 varEnv 是 全局环境记录 ,则:
a. 令 fnDefinable 为
? varEnv .CanDeclareGlobalFunction(fn )。
b. 如果 fnDefinable 为
false ,则抛出一个 TypeError 异常。
2. 将 fn 添加到 declaredFunctionNames 。
3. 将 d 插入为 functionsToInitialize
的第一个元素。
11. 令 declaredVarNames 为一个新的空 列表 。
12. 对于 varDeclarations 中的每个元素 d ,执行:
a. 如果 d 是 VariableDeclaration 、ForBinding 或
BindingIdentifier ,则:
i. 对于 d 的 BoundNames
中的每个字符串 vn ,执行:
1. 如果 declaredFunctionNames 不包含
vn ,则:
a. 如果 varEnv 是 全局环境记录 ,则:
i. 令 vnDefinable 为
? varEnv .CanDeclareGlobalVar(vn )。
ii. 如果 vnDefinable 为
false ,则抛出一个 TypeError 异常。
b. 如果 declaredVarNames 不包含 vn ,则:
i. 将 vn 添加到
declaredVarNames 。
13.
注意:附录 B.3.2.3
在此点添加了额外的步骤。
14.
注意:在此算法步骤之后不会发生异常终止,除非 varEnv 是 全局环境记录 并且 全局对象 是一个 代理异类对象 。
15. 令 lexDeclarations 为 body 的 LexicallyScopedDeclarations 。
16. 对于 lexDeclarations 中的每个元素 d ,执行:
a. 注意:词法声明的名称只在这里被实例化,但不初始化。
b. 对于 d 的 BoundNames
中的每个元素 dn ,执行:
i. 如果 d 的 IsConstantDeclaration
为 true ,则:
1. 执行
? lexEnv .CreateImmutableBinding(dn , true )。
ii. 否则:
1. 执行
? lexEnv .CreateMutableBinding(dn , false )。
17. 对于 functionsToInitialize 中的每个 解析节点 f ,执行:
a. 令 fn 为 f 的 BoundNames
的唯一元素。
b. 令 fo 为 f 的 InstantiateFunctionObject ,参数为
lexEnv 和 privateEnv 。
c. 如果 varEnv 是一个 全局环境记录 ,则:
i. 执行
? varEnv .CreateGlobalFunctionBinding(fn , fo ,
true )。
d. 否则:
i. 令 bindingExists 为
! varEnv .HasBinding(fn )。
ii. 如果 bindingExists 为 false ,则:
1. 注意:由于步骤 14
之前的验证,以下调用不会返回 异常完成记录 。
2. 执行
! varEnv .CreateMutableBinding(fn , true )。
3. 执行
! varEnv .InitializeBinding(fn , fo )。
iii. 否则:
1. 执行
! varEnv .SetMutableBinding(fn , fo ,
false )。
18. 对于 declaredVarNames 中的每个字符串 vn ,执行:
a. 如果 varEnv 是一个 全局环境记录 ,则:
i. 执行
? varEnv .CreateGlobalVarBinding(vn , true )。
b. 否则:
i. 令 bindingExists 为
! varEnv .HasBinding(vn )。
ii. 如果 bindingExists 为 false ,则:
1. 注意:由于步骤 14
之前的验证,以下调用不会返回 异常完成记录 。
2. 执行
! varEnv .CreateMutableBinding(vn , true )。
3. 执行
! varEnv .InitializeBinding(vn , undefined )。
19. 返回 unused 。
注
19.2.2 isFinite(number )
该函数是内置对象%isFinite% 。
它在调用时执行以下步骤:
1. 令 num 为 ? ToNumber (number )。
2. 如果 num 不是 有限 的,返回 false 。
3. 否则,返回 true 。
19.2.3 isNaN(number )
该函数是内置对象%isNaN% 。
它在调用时执行以下步骤:
1. 令 num 为 ? ToNumber (number )。
2. 如果 num 是 NaN ,返回
true 。
3. 否则,返回 false 。
注
ECMAScript 代码测试值 X
是否为 NaN 的可靠方法是使用形式为 X !== X
的表达式。仅当
X
为 NaN 时,结果才会是 true 。
19.2.4 parseFloat(string )
此函数通过将string 参数的内容解释为十进制文字来生成一个数字值。
它是内置对象%parseFloat% 。
它在调用时执行以下步骤:
1. 令 inputString 为 ? ToString (string )。
2. 令 trimmedString 为 ! TrimString (inputString ,
start )。
3. 令 trimmed 为 StringToCodePoints (trimmedString )。
4. 令 trimmedPrefix 为满足 StrDecimalLiteral 语法的
trimmed 的最长前缀,这可能是 trimmed 本身。如果没有这样的前缀,返回 NaN 。
5. 令 parsedNumber 为 ParseText (trimmedPrefix ,
StrDecimalLiteral )。
6. 断言 :parsedNumber 是一个
解析节点 。
7. 返回 StringNumericValue (parsedNumber )。
注
此函数可能仅将string 的前导部分解释为数字值;它会忽略任何不能解释为十进制文字符号的代码单元,并且不会提供任何指示被忽略的代码单元。
19.2.5 parseInt(string , radix )
该函数根据指定的radix 解释string 的内容来生成一个整数integral
Number 。string 中的前导空白会被忽略。如果radix 被强制转换为0(例如当它是undefined 时),则假定为10,除非数字表示以"0x" 或"0X" 开头,在这种情况下假定为16。如果radix 是16,则数字表示可以选择性地以"0x" 或"0X" 开头。
它是内置对象%parseInt% 。
它在调用时执行以下步骤:
1. 令 inputString 为 ? ToString (string )。
2. 令 S 为 ! TrimString (inputString ,
start )。
3. 令 sign 为 1。
4. 如果 S 不是空的且S 的第一个代码单元是代码单元
0x002D(HYPHEN-MINUS),则将 sign 设为 -1。
5. 如果 S 不是空的且S 的第一个代码单元是代码单元 0x002B(PLUS SIGN)或代码单元
0x002D(HYPHEN-MINUS),则将 S 设为 子字符串 从索引 1 开始的部分。
6. 令 R 为 ℝ (? ToInt32 (radix ))。
7. 令 stripPrefix 为 true 。
8. 如果 R ≠ 0,则
a. 如果 R < 2 或 R >
36,返回NaN 。
b. 如果 R ≠ 16,将 stripPrefix
设为false 。
9. 否则,
a. 将 R 设为 10。
10. 如果 stripPrefix 为 true ,则
a. 如果 S 的长度至少为2且S 的前两个代码单元为
"0x" 或 "0X" ,则
i. 将 S 设为 子字符串 从索引 2 开始的部分。
ii. 将 R 设为 16。
11. 如果 S 包含一个不是R 进制的数字的代码单元,令 end 为
S 中第一个这样的代码单元的索引;否则,令 end 为 S 的长度。
12. 令 Z 为 子字符串 从0到end 的S 。
13. 如果 Z 是空的,返回 NaN 。
14. 令 mathInt 为 Z
用R 进制表示的整数值,使用字母A 到Z 和a 到z 表示值为10到35的数字。(但是,如果R =
10并且Z 包含超过20个有效数字,则第20个之后的每个有效数字可以被0替换,这取决于实现;如果R 不是2、4、8、10、16或32中的一个,则mathInt 可能是一个实现近似 的整数 ,表示Z 在R 进制表示的整数 值。)
15. 如果 mathInt = 0,则
a. 如果 sign = -1,返回 -0 𝔽 。
b. 返回 +0 𝔽 。
16. 返回 𝔽 (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 的新版本,其中每个转义序列和 UTF-8 编码将被 encodeURI
函数引入的排序替换为它所表示的代码点的 UTF-16 编码。无法通过
encodeURI
引入的转义序列不会被替换。
这是 %decodeURI% 内置对象。
调用时执行以下步骤:
1. 令 uriString 为 ? ToString (encodedURI )。
2. 令 preserveEscapeSet 为
";/?:@&=+$,#" 。
3. 返回 ? Decode (uriString ,
preserveEscapeSet )。
19.2.6.2 decodeURIComponent ( encodedURIComponent )
此函数计算 URI 的新版本,其中每个转义序列和 UTF-8 编码将被 encodeURIComponent
函数引入的排序替换为它所表示的代码点的 UTF-16 编码。
这是 %decodeURIComponent% 内置对象。
调用时执行以下步骤:
1. 令 componentString 为 ? ToString (encodedURIComponent )。
2. 令 preserveEscapeSet 为空字符串。
3. 返回 ? Decode (componentString ,
preserveEscapeSet )。
19.2.6.3 encodeURI ( uri )
此函数计算 UTF-16 编码 (6.1.4 ) URI
的新版本,其中每个特定代码点实例被替换为一个、两个、三个或四个表示代码点的 UTF-8 编码的转义序列。
这是 %encodeURI% 内置对象。
调用时执行以下步骤:
1. 令 uriString 为 ? ToString (uri )。
2. 令 extraUnescaped 为 ";/?:@&=+$,#" 。
3. 返回 ? Encode (uriString ,
extraUnescaped )。
19.2.6.4 encodeURIComponent ( uriComponent )
此函数计算 UTF-16 编码 (6.1.4 ) URI
的新版本,其中每个特定代码点实例被替换为一个、两个、三个或四个表示代码点的 UTF-8 编码的转义序列。
这是 %encodeURIComponent% 内置对象。
调用时执行以下步骤:
1. 令 componentString 为 ? ToString (uriComponent )。
2. 令 extraUnescaped 为空字符串。
3. 返回 ? Encode (componentString ,
extraUnescaped )。
19.2.6.5 Encode ( string , extraUnescaped )
抽象操作 Encode 接受参数 string (字符串)和 extraUnescaped (字符串),并返回一个 包含 字符串的
正常完成 或 抛出完成 。它执行 URI
编码和转义,如 6.1.4 所述,将
string 解释为 UTF-16 编码的代码点序列。如果某个字符在 RFC 2396 中被标识为未保留,或者出现在 extraUnescaped
中,则不对其进行转义。调用时执行以下步骤:
1. 令 len 为 string 的长度。
2. 令 R 为空字符串。
3. 令 alwaysUnescaped 为 ASCII 单词字符 和
"-.!~*'()" 的 字符串连接 。
4. 令 unescapedSet 为 alwaysUnescaped 和
extraUnescaped 的 字符串连接 。
5. 令 k 为 0。
6. 重复,当 k < len 时,
a. 令 C 为 string 中索引 k 处的代码单元。
b. 如果 unescapedSet 包含 C ,则
i. 令 k 为 k + 1。
ii. 令 R 为 R 和 C 的 字符串连接 。
c. 否则,
i. 令 cp 为 CodePointAt (string ,
k )。
ii. 如果 cp .[[IsUnpairedSurrogate]] 为 true ,则抛出
URIError 异常。
iii. 令 k 为 k + cp .[[CodeUnitCount]] 。
iv. 令 Octets 为将 UTF-8 转换应用于 cp .[[CodePoint]] 结果的 字节列表 。
v. 对 Octets 的每个元素 octet ,
1. 令 hex 为 octet
的字符串表示,格式化为大写的十六进制数。
2. 令 R 为 R 、"%" 和
StringPad (hex ,
2, "0" , start ) 的 字符串连接 。
7. 返回 R 。
注
由于百分比编码用于表示单个字节,因此单个代码点可能表示为多个连续的转义序列(每个转义序列对应其 8 位 UTF-8 代码单元)。
19.2.6.6 Decode ( string , preserveEscapeSet )
抽象操作 Decode 接受参数 string (字符串)和 preserveEscapeSet (字符串),并返回一个 包含 字符串的
正常完成 或 抛出完成 。它执行 URI
解码,保留 preserveEscapeSet 中对应的基本拉丁字符的任何转义序列。调用时执行以下步骤:
1. 令 len 为 string 的长度。
2. 令 R 为空字符串。
3. 令 k 为 0。
4. 重复,当 k < len 时,
a. 令 C 为 string 中索引 k 处的代码单元。
b. 令 S 为 C 。
c. 如果 C 是代码单元 0x0025(百分号),则
i. 如果 k + 3 > len ,则抛出
URIError 异常。
ii. 令 escape 为 string 从 k 到
k + 3 的 子字符串 。
iii. 令 B 为 ParseHexOctet (string ,
k + 1)。
iv. 如果 B 不是 整数 ,则抛出
URIError 异常。
v. 令 k 为 k + 2。
vi. 令 n 为 B 中的前导 1 位的数量。
vii. 如果 n = 0,则
1. 令 asciiChar 为数值为 B 的代码单元。
2. 如果 preserveEscapeSet 包含
asciiChar ,则将 S 设为 escape 。否则,将 S 设为
asciiChar 。
viii. 否则,
1. 如果 n = 1 或 n > 4,则抛出
URIError 异常。
2. 令 Octets 为 « B »。
3. 令 j 为 1。
4. 重复,当 j < n 时,
a. 令 k 为 k + 1。
b. 如果 k + 3 > len ,则抛出
URIError 异常。
c. 如果 string 中索引 k 处的代码单元不是代码单元
0x0025(百分号),则抛出 URIError 异常。
d. 令 continuationByte 为 ParseHexOctet (string ,
k + 1)。
e. 如果 continuationByte 不是 整数 ,则抛出
URIError 异常。
f. 将 continuationByte 附加到
Octets 。
g. 令 k 为 k + 2。
h. 令 j 为 j + 1。
5. 断言 :Octets 的长度为
n 。
6. 如果 Octets 不包含有效的 UTF-8 编码的 Unicode 代码点,则抛出
URIError 异常。
7. 令 V 为通过应用 UTF-8 转换从 Octets
中获得的代码点,即从 字节列表
到 21 位值。
8. 将 S 设置为 UTF16EncodeCodePoint (V )。
d. 令 R 为 R 和 S 的 字符串连接 。
e. 令 k 为 k + 1。
5. 返回 R 。
注
RFC 3629 禁止解码无效的 UTF-8 字节序列。例如,无效序列 0xC0 0x80 不得解码为代码单元 0x0000。Decode 算法的实现需要在遇到此类无效序列时抛出
URIError 。
19.2.6.7 ParseHexOctet ( string , position )
抽象操作 ParseHexOctet 接受参数 string (字符串)和 position (非负整数),并返回一个非负整数或包含
SyntaxError 对象的非空列表。它在 string 中指定的 position 处将两个十六进制字符解析为一个无符号 8
位整数。调用时执行以下步骤:
1. 令 len 为 string 的长度。
2. 断言 :position + 2 ≤ len 。
3. 令 hexDigits 为 string 从 position 到
position + 2 的 子字符串 。
4. 令 parseResult 为 ParseText (StringToCodePoints (hexDigits ),
HexDigits [~Sep] )。
5. 如果 parseResult 不是 语法节点 ,返回
parseResult 。
6. 令 n 为 parseResult 的 MV。
7. 断言 :n 在 0 到 255 的 闭区间 内。
8. 返回 n 。
19.3 全局对象的构造器属性
19.3.1 AggregateError ( . . . )
见 20.5.7.1 。
19.3.2 Array ( . . . )
见 23.1.1 。
19.3.3 ArrayBuffer ( . . . )
见 25.1.4 。
19.3.4 BigInt ( . . . )
见 21.2.1 。
19.3.5 BigInt64Array ( . . . )
见 23.2.5 。
19.3.6 BigUint64Array ( . . . )
见 23.2.5 。
19.3.7 Boolean ( . . . )
见 20.3.1 。
19.3.8 DataView ( . . . )
见 25.3.2 。
19.3.9 Date ( . . . )
见 21.4.2 。
19.3.10 Error ( . . . )
见 20.5.1 。
19.3.11 EvalError ( . . . )
见 20.5.5.1 。
19.3.12 FinalizationRegistry ( . . . )
见 26.2.1 。
19.3.13 Float32Array ( . . . )
见 23.2.5 。
19.3.14 Float64Array ( . . . )
见 23.2.5 。
19.3.15 Function ( . . . )
见 20.2.1 。
19.3.16 Int8Array ( . . . )
见 23.2.5 。
19.3.17 Int16Array ( . . . )
见 23.2.5 。
19.3.18 Int32Array ( . . . )
见 23.2.5 。
19.3.19 Map ( . . . )
见 24.1.1 。
19.3.20 Number ( . . . )
见 21.1.1 。
19.3.21 Object ( . . . )
见 20.1.1 。
19.3.22 Promise ( . . . )
见 27.2.3 。
19.3.23 Proxy ( . . . )
见 28.2.1 。
19.3.24 RangeError ( . . . )
见 20.5.5.2 。
19.3.25 ReferenceError ( . . . )
见 20.5.5.3 。
19.3.26 RegExp ( . . . )
见 22.2.4 。
19.3.27 Set ( . . . )
见 24.2.1 。
19.3.28 SharedArrayBuffer ( . . . )
见 25.2.3 。
19.3.29 String ( . . . )
见 22.1.1 。
19.3.30 Symbol ( . . . )
见 20.4.1 。
19.3.31 SyntaxError ( . . . )
见 20.5.5.4 。
19.3.32 TypeError ( . . . )
见 20.5.5.5 。
19.3.33 Uint8Array ( . . . )
见 23.2.5 。
19.3.34 Uint8ClampedArray ( . . . )
见 23.2.5 。
19.3.35 Uint16Array ( . . . )
见 23.2.5 。
19.3.36 Uint32Array ( . . . )
见 23.2.5 。
19.3.37 URIError ( . . . )
见 20.5.5.6 。
19.3.38 WeakMap ( . . . )
见 24.3.1 。
19.3.39 WeakRef ( . . . )
见 26.1.1 。
19.3.40 WeakSet ( . . . )
见 24.4 。
19.4 全局对象的其他属性
19.4.1 Atomics
见 25.4 。
19.4.2 JSON
见 25.5 。
19.4.3 Math
见 21.3 。
19.4.4 Reflect
见 28.1 。
20 基本对象
20.1 Object 对象
20.1.1 Object 构造函数
Object 构造函数 :
是 %Object% 。
是 "Object" 属性在 全局对象 中的初始值。
当作为 构造函数 调用时,创建一个新的 普通对象 。
当作为函数而不是 构造函数 调用时,执行类型转换。
可以用作类定义的 extends
子句的值。
20.1.1.1 Object ( [ value ] )
此函数调用时执行以下步骤:
1. 如果 NewTarget 既不是 undefined 也不是 活动函数对象 ,则
a. 返回 ? OrdinaryCreateFromConstructor (NewTarget,
"%Object.prototype%" )。
2. 如果 value 是 undefined 或
null ,则返回 OrdinaryObjectCreate (%Object.prototype% )。
3. 返回 ! ToObject (value )。
20.1.2 Object 构造函数的属性
Object 构造函数 :
20.1.2.1 Object.assign ( target , ...sources )
此函数将一个或多个源对象的所有可枚举自身属性的值复制到一个 target 对象。
调用时执行以下步骤:
1. 令 to 为 ? ToObject (target )。
2. 如果只传递了一个参数,则返回 to 。
3. 对于 sources 的每个元素 nextSource ,执行以下操作:
a. 如果 nextSource 既不是 undefined 也不是
null ,则
i. 令 from 为 ! ToObject (nextSource )。
ii. 令 keys 为 ? from .[[OwnPropertyKeys]] () 。
iii. 对于 keys 的每个元素 nextKey ,执行以下操作:
1. 令 desc 为 ? from .[[GetOwnProperty]] (nextKey )。
2. 如果 desc 不是 undefined 并且
desc .[[Enumerable]] 为 true ,则
a. 令 propValue 为 ? Get (from , nextKey )。
b. 执行 ? Set (to , nextKey ,
propValue , true )。
4. 返回 to 。
此函数的 "length" 属性为 2 𝔽 。
20.1.2.2 Object.create ( O , Properties )
此函数创建一个具有指定原型的新对象。
调用时执行以下步骤:
1. 如果 O 不是对象 并且
O 不是 null ,则抛出 TypeError 异常。
2. 令 obj 为 OrdinaryObjectCreate (O )。
3. 如果 Properties 不是 undefined ,则
a. 返回 ? ObjectDefineProperties (obj ,
Properties )。
4. 返回 obj 。
20.1.2.3 Object.defineProperties ( O , Properties )
此函数添加自身属性和/或更新对象现有自身属性的属性。
调用时执行以下步骤:
1. 如果 O 不是对象 ,则抛出
TypeError 异常。
2. 返回 ? ObjectDefineProperties (O , Properties )。
20.1.2.3.1 ObjectDefineProperties ( O , Properties )
抽象操作 ObjectDefineProperties 接受参数 O (对象)和 Properties (ECMAScript 语言值 )并返回
包含 对象的正常完成或
抛出完成 。调用时执行以下步骤:
1. 令 props 为 ? ToObject (Properties )。
2. 令 keys 为 ? props .[[OwnPropertyKeys]] () 。
3. 令 descriptors 为一个新的空 列表 。
4. 对于 keys 的每个元素 nextKey ,执行以下操作:
a. 令 propDesc 为 ? props .[[GetOwnProperty]] (nextKey )。
b. 如果 propDesc 不是 undefined 并且
propDesc .[[Enumerable]] 为 true ,则
i. 令 descObj 为 ? Get (props , nextKey )。
ii. 令 desc 为 ? ToPropertyDescriptor (descObj )。
iii. 将 记录
{ [[Key]] : nextKey , [[Descriptor]] : desc } 附加到 descriptors 。
5. 对于 descriptors 的每个元素 property ,执行以下操作:
a. 执行 ? DefinePropertyOrThrow (O ,
property .[[Key]] , property .[[Descriptor]] )。
6. 返回 O 。
20.1.2.4 Object.defineProperty ( O , P ,
Attributes )
此函数添加自身属性和/或更新对象现有自身属性的属性。
调用时执行以下步骤:
1. 如果 O 不是对象 ,则抛出
TypeError 异常。
2. 令 key 为 ? ToPropertyKey (P )。
3. 令 desc 为 ? ToPropertyDescriptor (Attributes )。
4. 执行 ? DefinePropertyOrThrow (O , key ,
desc )。
5. 返回 O 。
20.1.2.5 Object.entries ( O )
此函数调用时执行以下步骤:
1. 令 obj 为 ? ToObject (O )。
2. 令 entryList 为 ? EnumerableOwnProperties (obj ,
key+value )。
3. 返回 CreateArrayFromList (entryList )。
20.1.2.6 Object.freeze ( O )
此函数调用时执行以下步骤:
1. 如果 O 不是对象 ,则返回
O 。
2. 令 status 为 ? SetIntegrityLevel (O , frozen )。
3. 如果 status 为 false ,则抛出
TypeError 异常。
4. 返回 O 。
20.1.2.7 Object.fromEntries ( iterable )
此函数调用时执行以下步骤:
1. 执行 ? RequireObjectCoercible (iterable )。
2. 令 obj 为 OrdinaryObjectCreate (%Object.prototype% )。
3. 断言 :obj 是一个没有自身属性的可扩展 普通对象 。
4. 令 closure 为一个新的 抽象闭包 ,具有参数
(key , value ),捕获 obj 并在调用时执行以下步骤:
a. 令 propertyKey 为 ? ToPropertyKey (key )。
b. 执行 ! CreateDataPropertyOrThrow (obj ,
propertyKey , value )。
c. 返回 undefined 。
5. 令 adder 为 CreateBuiltinFunction (closure ,
2, "" , « »)。
6. 返回 ? AddEntriesFromIterable (obj , iterable ,
adder )。
注
为 adder 创建的函数从不直接可供 ECMAScript 代码访问。
20.1.2.8 Object.getOwnPropertyDescriptor ( O , P )
此函数调用时执行以下步骤:
1. 令 obj 为 ? ToObject (O )。
2. 令 key 为 ? ToPropertyKey (P )。
3. 令 desc 为 ? obj .[[GetOwnProperty]] (key ) 。
4. 返回 FromPropertyDescriptor (desc )。
20.1.2.9 Object.getOwnPropertyDescriptors ( O )
此函数调用时执行以下步骤:
1. 令 obj 为 ? ToObject (O )。
2. 令 ownKeys 为 ? obj .[[OwnPropertyKeys]] () 。
3. 令 descriptors 为 OrdinaryObjectCreate (%Object.prototype% )。
4. 对于 ownKeys 的每个元素 key ,执行以下操作:
a. 令 desc 为 ? obj .[[GetOwnProperty]] (key ) 。
b. 令 descriptor 为 FromPropertyDescriptor (desc )。
c. 如果 descriptor 不是 undefined ,执行
! CreateDataPropertyOrThrow (descriptors ,
key , descriptor )。
5. 返回 descriptors 。
20.1.2.10 Object.getOwnPropertyNames ( O )
此函数调用时执行以下步骤:
1. 返回 CreateArrayFromList (?
GetOwnPropertyKeys (O ,
string ))。
20.1.2.11 Object.getOwnPropertySymbols ( O )
此函数调用时执行以下步骤:
1. 返回 CreateArrayFromList (?
GetOwnPropertyKeys (O ,
symbol ))。
20.1.2.11.1 GetOwnPropertyKeys ( O , type )
抽象操作 GetOwnPropertyKeys 接受参数 O (ECMAScript
语言值 )和 type (string 或
symbol ),返回 包含 属性键的
列表 的正常完成或
抛出完成 。调用时执行以下步骤:
1. 令 obj 为 ? ToObject (O )。
2. 令 keys 为 ? obj .[[OwnPropertyKeys]] () 。
3. 令 nameList 为一个新的空 列表 。
4. 对于 keys 的每个元素 nextKey ,执行以下操作:
a. 如果 nextKey 是符号
并且 type 是 symbol ,或 nextKey 是字符串
并且 type 是 string ,则
i. 将 nextKey 附加到 nameList 。
5. 返回 nameList 。
20.1.2.12 Object.getPrototypeOf ( O )
此函数调用时执行以下步骤:
1. 令 obj 为 ? ToObject (O )。
2. 返回 ? obj .[[GetPrototypeOf]] () 。
20.1.2.13 Object.groupBy ( items , callbackfn )
注
callbackfn 应该是一个接受两个参数的函数。groupBy
按升序调用 callbackfn 一次,每次调用
items 中的一个元素,并构建一个新对象。callbackfn 返回的每个值都被强制转换为 属性键 。对于每个这样的
属性键 ,结果对象有一个键为该 属性键 的属性,其值是一个包含所有元素的数组,这些元素的
callbackfn 返回值被强制转换为该键。
callbackfn 以两个参数调用:元素的值和元素的索引。
groupBy
的返回值是一个对象,不从 %Object.prototype%
继承。
此函数调用时执行以下步骤:
1. 令 groups 为 ? GroupBy (items , callbackfn ,
property )。
2. 令 obj 为 OrdinaryObjectCreate (null )。
3. 对于 记录 { [[Key]] , [[Elements]] } g 的每个元素
groups ,执行以下操作:
a. 令 elements 为 CreateArrayFromList (g .[[Elements]] )。
b. 执行 ! CreateDataPropertyOrThrow (obj ,
g .[[Key]] , elements )。
4. 返回 obj 。
20.1.2.14 Object.hasOwn ( O , P )
此函数调用时执行以下步骤:
1. 令 obj 为 ? ToObject (O )。
2. 令 key 为 ? ToPropertyKey (P )。
3. 返回 ? HasOwnProperty (obj , key )。
20.1.2.15 Object.is ( value1 , value2 )
此函数调用时执行以下步骤:
1. 返回 SameValue (value1 ,
value2 )。
20.1.2.16 Object.isExtensible ( O )
此函数调用时执行以下步骤:
1. 如果 O 不是对象 ,则返回
false 。
2. 返回 ? IsExtensible (O )。
20.1.2.17 Object.isFrozen ( O )
此函数调用时执行以下步骤:
1. 如果 O 不是对象 ,则返回
true 。
2. 返回 ? TestIntegrityLevel (O ,
frozen )。
20.1.2.18 Object.isSealed ( O )
此函数调用时执行以下步骤:
1. 如果 O 不是对象 ,则返回
true 。
2. 返回 ? TestIntegrityLevel (O ,
sealed )。
20.1.2.19 Object.keys ( O )
此函数调用时执行以下步骤:
1. 令 obj 为 ? ToObject (O )。
2. 令 keyList 为 ? EnumerableOwnProperties (obj ,
key )。
3. 返回 CreateArrayFromList (keyList )。
20.1.2.20 Object.preventExtensions ( O )
此函数调用时执行以下步骤:
1. 如果 O 不是对象 ,则返回
O 。
2. 令 status 为 ? O .[[PreventExtensions]] () 。
3. 如果 status 为 false ,则抛出
TypeError 异常。
4. 返回 O 。
20.1.2.21 Object.prototype
Object.prototype
的初始值为 Object
原型对象 。
此属性具有 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
false } 的属性。
20.1.2.22 Object.seal ( O )
此函数调用时执行以下步骤:
1. 如果 O 不是对象 ,则返回
O 。
2. 令 status 为 ? SetIntegrityLevel (O , sealed )。
3. 如果 status 为 false ,则抛出
TypeError 异常。
4. 返回 O 。
20.1.2.23 Object.setPrototypeOf ( O , proto )
此函数调用时执行以下步骤:
1. 将 O 设为 ? RequireObjectCoercible (O )。
2. 如果 proto 不是对象 并且
proto 不是 null ,则抛出 TypeError 异常。
3. 如果 O 不是对象 ,则返回
O 。
4. 令 status 为 ? O .[[SetPrototypeOf]] (proto ) 。
5. 如果 status 为 false ,则抛出
TypeError 异常。
6. 返回 O 。
20.1.2.24 Object.values ( O )
此函数调用时执行以下步骤:
1. 令 obj 为 ? ToObject (O )。
2. 令 valueList 为 ? EnumerableOwnProperties (obj ,
value )。
3. 返回 CreateArrayFromList (valueList )。
20.1.3 Object 原型对象的属性
Object 原型对象 :
是 %Object.prototype% 。
具有内部槽 [[Extensible]] ,其值为 true 。
具有为普通对象 定义的内部方法,但 [[SetPrototypeOf]] 方法除外,该方法在 10.4.7.1
中定义。(因此,它是一个不可变原型异域对象 。)
具有内部槽 [[Prototype]] ,其值为 null 。
20.1.3.1 Object.prototype.constructor
Object.prototype.constructor
的初始值是 %Object% 。
20.1.3.2 Object.prototype.hasOwnProperty ( V )
调用此方法时,执行以下步骤:
1. 令 P 为
? ToPropertyKey (V )。
2. 令 O 为
? ToObject (this 值)。
3. 返回 ? HasOwnProperty (O , P )。
注
步骤 1 和 2 的排序是为了确保在
this 值为 undefined 或 null 的情况下,步骤 1
在本规范的先前版本中会抛出的任何异常将继续被抛出。
20.1.3.3 Object.prototype.isPrototypeOf ( V )
调用此方法时,执行以下步骤:
1. 如果 V 不是对象 ,返回 false 。
2. 令 O 为
? ToObject (this 值)。
3. 重复以下步骤:
a. 设置 V 为 ? V .[[GetPrototypeOf]] () 。
b. 如果 V 是 null ,返回
false 。
c. 如果 SameValue (O ,
V ) 是 true ,返回 true 。
注
步骤 1 和 2
的排序保留了本规范先前版本所指定的行为,即在 V 不是对象且 this 值是 undefined 或
null 的情况下。
20.1.3.4 Object.prototype.propertyIsEnumerable ( V )
调用此方法时,执行以下步骤:
1. 令 P 为
? ToPropertyKey (V )。
2. 令 O 为
? ToObject (this 值)。
3. 令 desc 为 ? O .[[GetOwnProperty]] (P )。
4. 如果 desc 是 undefined ,返回
false 。
5. 返回 desc .[[Enumerable]] 。
注 1
注 2
步骤 1 和
2 的排序是为了确保即使
this 值是 undefined 或 null ,步骤 1
在本规范的先前版本中将抛出的任何异常将继续被抛出。
20.1.3.5 Object.prototype.toLocaleString ( [ reserved1 [ ,
reserved2 ] ] )
调用此方法时,执行以下步骤:
1. 令 O 为 this 值。
2. 返回 ? 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 ( )
调用此方法时,执行以下步骤:
1. 如果 this 值是 undefined ,则返回
"[object Undefined]" 。
2. 如果 this 值是 null ,则返回
"[object Null]" 。
3. 令 O 为 ! ToObject (this 值)。
4. 令 isArray 为 ? IsArray (O )。
5. 如果 isArray 为 true ,则令
builtinTag 为 "Array" 。
6. 否则,如果 O 具有 [[ParameterMap]]
内部插槽,则令 builtinTag 为 "Arguments" 。
7. 否则,如果 O 具有 [[Call]] 内部方法,则令
builtinTag 为 "Function" 。
8. 否则,如果 O 具有 [[ErrorData]]
内部插槽,则令 builtinTag 为 "Error" 。
9. 否则,如果 O 具有 [[BooleanData]]
内部插槽,则令 builtinTag 为 "Boolean" 。
10. 否则,如果 O 具有 [[NumberData]]
内部插槽,则令 builtinTag 为 "Number" 。
11. 否则,如果 O 具有 [[StringData]]
内部插槽,则令 builtinTag 为 "String" 。
12. 否则,如果 O 具有 [[DateValue]]
内部插槽,则令 builtinTag 为 "Date" 。
13. 否则,如果 O 具有 [[RegExpMatcher]]
内部插槽,则令 builtinTag 为 "RegExp" 。
14. 否则,令 builtinTag 为 "Object" 。
15. 令 tag 为 ? Get (O ,
@@toStringTag )。
16. 如果 tag 不是一个字符串 ,则将
tag 设为 builtinTag 。
17. 返回 字符串连接 "[object
" 、tag 和 "]" 。
注
历史上,此方法偶尔被用来访问 [[Class]] 内部插槽的字符串值,该插槽在之前的版本规范中用作各种内置对象的名义类型标签。上面的
toString
定义保留了兼容性,以供使用 toString
作为这些特定内置对象的测试的遗留代码使用。它不提供其他种类的内置或程序定义对象的可靠类型测试机制。此外,程序可以使用 @@toStringTag
以某种方式使这些遗留类型测试失效。
20.1.3.7 Object.prototype.valueOf ( )
调用此方法时,执行以下步骤:
1. 返回 ? ToObject (this 值)。
20.1.3.8 Object.prototype.__proto__
Object.prototype.__proto__
是一个 存取器属性 ,其属性为
{ [[Enumerable]] : false , [[Configurable]] : true }。[[Get]]
和 [[Set]] 属性定义如下:
20.1.3.8.1 get Object.prototype.__proto__
[[Get]] 属性的值是一个内置函数,不需要参数。调用时执行以下步骤:
1. 令 O 为 ? ToObject (this
值)。
2. 返回 ? O .[[GetPrototypeOf]] () 。
20.1.3.8.2 set Object.prototype.__proto__
[[Set]] 属性的值是一个内置函数,接受一个参数 proto 。调用时执行以下步骤:
1. 令 O 为 ? RequireObjectCoercible (this
值)。
2. 如果 proto 不是对象 并且
proto 不是 null ,则返回
undefined 。
3. 如果 O 不是对象 ,则返回
undefined 。
4. 令 status 为 ? O .[[SetPrototypeOf]] (proto ) 。
5. 如果 status 为 false ,则抛出
TypeError 异常。
6. 返回 undefined 。
20.1.3.9 旧版 Object.prototype 访问器方法
20.1.3.9.1 Object.prototype.__defineGetter__ ( P ,
getter )
调用此方法时,执行以下步骤:
1. 令 O 为 ? ToObject (this
值)。
2. 如果 IsCallable (getter ) 为
false , 抛出一个 TypeError 异常。
3. 令 desc 为 PropertyDescriptor { [[Get]] : getter , [[Enumerable]] :
true , [[Configurable]] : true }。
4. 令 key 为 ? ToPropertyKey (P )。
5. 执行 ? DefinePropertyOrThrow (O , key ,
desc )。
6. 返回 undefined 。
20.1.3.9.2 Object.prototype.__defineSetter__ ( P ,
setter )
调用此方法时,执行以下步骤:
1. 令 O 为 ? ToObject (this
值)。
2. 如果 IsCallable (setter ) 为
false , 抛出一个 TypeError 异常。
3. 令 desc 为 PropertyDescriptor { [[Set]] : setter , [[Enumerable]] :
true , [[Configurable]] : true }。
4. 令 key 为 ? ToPropertyKey (P )。
5. 执行 ? DefinePropertyOrThrow (O , key ,
desc )。
6. 返回 undefined 。
20.1.3.9.3 Object.prototype.__lookupGetter__ ( P )
调用此方法时,执行以下步骤:
1. 令 O 为 ? ToObject (this
值)。
2. 令 key 为 ? ToPropertyKey (P )。
3. 重复,
a. 令 desc 为 ? O .[[GetOwnProperty]] (key )。
b. 如果 desc 不是 undefined , 则
i. 如果 IsAccessorDescriptor (desc )
为 true , 返回 desc .[[Get]] 。
ii. 返回 undefined 。
c. 将 O 设为 ? O .[[GetPrototypeOf]] () 。
d. 如果 O 是 null , 返回
undefined 。
20.1.3.9.4 Object.prototype.__lookupSetter__ ( P )
调用此方法时,执行以下步骤:
1. 令 O 为 ? ToObject (this
值)。
2. 令 key 为 ? ToPropertyKey (P )。
3. 重复,
a. 令 desc 为 ? O .[[GetOwnProperty]] (key )。
b. 如果 desc 不是 undefined , 则
i. 如果 IsAccessorDescriptor (desc )
为 true , 返回 desc .[[Set]] 。
ii. 返回 undefined 。
c. 将 O 设为 ? O .[[GetPrototypeOf]] () 。
d. 如果 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 )
最后一个参数(如果有)指定函数的主体(可执行代码);任何前面的参数指定形式参数。
当调用此函数时,执行以下步骤:
1. 让 C 为活动函数对象 。
2. 如果没有提供 bodyArg ,将 bodyArg 设置为空字符串。
3. 返回 ? CreateDynamicFunction (C , NewTarget,
normal , parameterArgs , bodyArg )。
注
可以有一个参数用于指定每个形式参数,但这不是必要的。例如,以下三个表达式生成相同的结果:
new Function ("a" , "b" , "c" , "return a+b+c" )
new Function ("a, b, c" , "return a+b+c" )
new Function ("a,b" , "c" , "return a+b+c" )
20.2.1.1.1 CreateDynamicFunction ( constructor ,
newTarget , kind , parameterArgs , bodyArg )
抽象操作 CreateDynamicFunction 接受参数 constructor (一个 构造函数 ),newTarget (一个构造函数 ),kind (normal ,generator ,async 或async-generator ),parameterArgs (一个列表 ECMAScript
语言值),和bodyArg (一个ECMAScript
语言值 ),并返回一个正常完成值 包含的
ECMAScript 函数对象 或抛出完成值 。constructor
是执行此操作的 构造函数 函数。newTarget
是最初应用于new
的 构造函数 。parameterArgs 和bodyArg 反映传递给constructor 的参数值。调用时执行以下步骤:
1. 如果 newTarget 是 undefined ,将
newTarget 设置为 constructor 。
2. 如果 kind 是 normal ,那么
a. 让 prefix 为 "function" 。
b. 让 exprSym 为语法符号 FunctionExpression 。
c. 让 bodySym 为语法符号 FunctionBody [~Yield,
~Await] 。
d. 让 parameterSym 为语法符号 FormalParameters [~Yield,
~Await] 。
e. 让 fallbackProto 为
"%Function.prototype%" 。
3. 否则,如果 kind 是 generator ,那么
a. 让 prefix 为 "function*" 。
b. 让 exprSym 为语法符号 GeneratorExpression 。
c. 让 bodySym 为语法符号 GeneratorBody 。
d. 让 parameterSym 为语法符号 FormalParameters [+Yield,
~Await] 。
e. 让 fallbackProto 为
"%GeneratorFunction.prototype%" 。
4. 否则,如果 kind 是 async ,那么
a. 让 prefix 为 "async function" 。
b. 让 exprSym 为语法符号 AsyncFunctionExpression 。
c. 让 bodySym 为语法符号 AsyncFunctionBody 。
d. 让 parameterSym 为语法符号 FormalParameters [~Yield,
+Await] 。
e. 让 fallbackProto 为
"%AsyncFunction.prototype%" 。
5. 否则,
a. 断言 :kind 是
async-generator 。
b. 让 prefix 为 "async function*" 。
c. 让 exprSym 为语法符号 AsyncGeneratorExpression 。
d. 让 bodySym 为语法符号 AsyncGeneratorBody 。
e. 让 parameterSym 为语法符号 FormalParameters [+Yield,
+Await] 。
f. 让 fallbackProto 为
"%AsyncGeneratorFunction.prototype%" 。
6. 让 argCount 为 parameterArgs 中元素的数量。
7. 让 bodyString 为 ? ToString (bodyArg )。
8. 让 parameterStrings 为一个新的空列表 。
9. 对于 parameterArgs 中的每个元素 arg ,执行
a. 将 ? ToString (arg ) 追加到 parameterStrings 。
10. 让 currentRealm 为当前 Realm 记录 。
11. 执行 ? HostEnsureCanCompileStrings (currentRealm ,
parameterStrings , bodyString , false )。
12. 将 P 设置为空字符串。
13. 如果 argCount > 0,那么
a. 将 P 设置为 parameterStrings [0]。
b. 将 k 设置为 1。
c. 重复以下步骤,直到 k < argCount ,
i. 让 nextArgString 为
parameterStrings [k ]。
ii. 将 P 设置为 字符串连接
P 、"," (逗号)和 nextArgString 。
iii. 将 k 设置为 k + 1。
14. 将 bodyParseString 设置为 字符串连接
0x000A(换行符)、bodyString 和 0x000A(换行符)。
15. 将 sourceString 设置为 字符串连接
prefix 、" anonymous(" 、P 、0x000A(换行符)、")
{" 、bodyParseString 和 "}" 。
16. 将 sourceText 设置为 StringToCodePoints (sourceString )。
17. 将 parameters 设置为 ParseText (StringToCodePoints (P )、parameterSym )。
18. 如果 parameters 是错误列表 ,抛出
SyntaxError 异常。
19. 将 body 设置为 ParseText (StringToCodePoints (bodyParseString )、bodySym )。
20. 如果 body 是错误列表 ,抛出
SyntaxError 异常。
21.
注意:参数和主体是分别解析的,以确保每个单独有效。例如,new Function("/*", "*/ ) {")
不会解析为一个函数。
22. 注意:如果达到此步骤,sourceText 必须具有 exprSym
的语法(尽管逆推不成立)。接下来的两个步骤的目的是直接强制执行适用于 exprSym 的任何早期错误规则。
23. 将 expr 设置为 ParseText (sourceText 、exprSym )。
24. 如果 expr 是错误列表 ,抛出
SyntaxError 异常。
25. 让 proto 为 ? GetPrototypeFromConstructor (newTarget 、fallbackProto )。
26. 让 env 为 currentRealm .[[GlobalEnv]] 。
27. 让 privateEnv 为 null 。
28. 让 F 为 OrdinaryFunctionCreate (proto 、sourceText 、parameters 、body 、non-lexical-this 、env 、privateEnv )。
29. 执行 SetFunctionName (F 、"anonymous" )。
30. 如果 kind 是 generator ,那么
a. 让 prototype 为 OrdinaryObjectCreate (%GeneratorFunction.prototype.prototype% )。
b. 执行 ! DefinePropertyOrThrow (F 、"prototype" 、PropertyDescriptor
{ [[Value]] : prototype 、[[Writable]] : true 、[[Enumerable]] : false 、[[Configurable]] : false })。
31. 否则,如果 kind 是
async-generator ,那么
a. 让 prototype 为 OrdinaryObjectCreate (%AsyncGeneratorFunction.prototype.prototype% )。
b. 执行 ! DefinePropertyOrThrow (F 、"prototype" 、PropertyDescriptor
{ [[Value]] : prototype 、[[Writable]] : true 、[[Enumerable]] : false 、[[Configurable]] : false })。
32. 否则,如果 kind 是 normal ,那么
a. 执行 MakeConstructor (F )。
33. 注意:kind 为 async 的函数不可构造,并且没有
[[Construct]] 内部方法或 "prototype" 属性。
34. 返回 F 。
注
CreateDynamicFunction 在它创建的任何 kind 不为 async 的函数上定义一个
"prototype" 属性,以提供函数作为 构造函数 使用的可能性。
20.2.2 Function 构造函数的属性
Function 构造函数 具有以下属性:
20.2.2.1 Function.prototype
Function.prototype
的值是 函数原型对象 。
该属性具有 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
false } 的属性。
20.2.3 Function 原型对象的属性
Function 原型对象 :
是 %Function.prototype% 。
本身是一个内置的 函数对象 。
接受任何参数,并在调用时返回 undefined 。
没有 [[Construct]] 内部方法;它不能与 new
运算符一起用作 构造函数 。
具有一个 [[Prototype]] 内部槽,其值为 %Object.prototype% 。
没有 "prototype" 属性。
具有一个 "length" 属性,其值为 +0 𝔽 。
具有一个 "name" 属性,其值为空字符串。
注
Function 原型对象被指定为一个 函数对象 ,以确保与 ECMAScript 2015 规范之前创建的
ECMAScript 代码的兼容性。
20.2.3.1 Function.prototype.apply ( thisArg , argArray
)
当调用此方法时,执行以下步骤:
1. 让 func 为 this 值。
2. 如果 IsCallable (func ) 为
false ,则抛出一个 TypeError 异常。
3. 如果 argArray 为 undefined 或
null ,则
a. 执行 PrepareForTailCall ()。
b. 返回 ? Call (func , thisArg )。
4. 让 argList 为 ? CreateListFromArrayLike (argArray )。
5. 执行 PrepareForTailCall ()。
6. 返回 ? Call (func , thisArg , argList )。
注 1
thisArg 值在没有修改的情况下作为 this 值传递。这与第 3 版的不同,第 3
版中,undefined 或 null 的 thisArg 会被替换为 全局对象 ,并且 ToObject 会应用于所有其他值,并且结果作为
this 值传递。即使 thisArg 没有被修改地传递,非严格函数 在进入函数时仍会执行这些转换。
注 2
如果 func 是一个箭头函数或一个 绑定函数异类对象 ,则
thisArg 将被该函数的 [[Call]] 忽略,在步骤 6 中。
20.2.3.2 Function.prototype.bind ( thisArg , ...args )
当调用此方法时,执行以下步骤:
1. 让 Target 为 this 值。
2. 如果 IsCallable (Target ) 为
false ,则抛出一个 TypeError 异常。
3. 让 F 为 ? BoundFunctionCreate (Target , thisArg ,
args )。
4. 设 L 为 0。
5. 让 targetHasLength 为 ? HasOwnProperty (Target , "length" )。
6. 如果 targetHasLength 为 true ,则
a. 让 targetLen 为 ? Get (Target , "length" )。
b. 如果 targetLen 是一个
Number ,则
i. 如果 targetLen 为
+∞ 𝔽 ,则
1. 设 L 为 +∞。
ii. 否则,如果 targetLen 为
-∞ 𝔽 ,则
1. 设 L 为 0。
iii. 否则,
1. 让 targetLenAsInt 为 ! ToIntegerOrInfinity (targetLen )。
2. 断言 :targetLenAsInt 是
有限的 。
3. 设 argCount 为 args 中元素的数量。
4. 设 L 为 最大值 (targetLenAsInt
- argCount , 0)。
7. 执行 SetFunctionLength (F ,
L )。
8. 让 targetName 为 ? Get (Target , "name" )。
9. 如果 targetName 不是一个
String ,则设 targetName 为空字符串。
10. 执行 SetFunctionName (F ,
targetName , "bound" )。
11. 返回 F 。
注 1
使用 Function.prototype.bind
创建的 函数对象 是 异类对象 。它们也没有
"prototype" 属性。
注 2
如果 Target 是一个箭头函数或一个 绑定函数异类对象 ,则传递给此方法的
thisArg 不会被后续调用 F 时使用。
20.2.3.3 Function.prototype.call ( thisArg , ...args )
当调用此方法时,执行以下步骤:
1. 让 func 为 this 值。
2. 如果 IsCallable (func ) 为
false ,则抛出一个 TypeError 异常。
3. 执行 PrepareForTailCall ()。
4. 返回 ? Call (func , thisArg , args )。
注 1
thisArg 值在没有修改的情况下作为 this 值传递。这与第 3 版的不同,第 3
版中,undefined 或 null 的 thisArg 会被替换为 全局对象 ,并且 ToObject 会应用于所有其他值,并且结果作为
this 值传递。即使 thisArg 没有被修改地传递,非严格函数 在进入函数时仍会执行这些转换。
注 2
如果 func 是一个箭头函数或一个 绑定函数异类对象 ,则
thisArg 将被该函数的 [[Call]] 忽略,在步骤 4 中。
20.2.3.4 Function.prototype.constructor
Function.prototype.constructor
的初始值是 %Function% 。
20.2.3.5 Function.prototype.toString ( )
当调用此方法时,执行以下步骤:
1. 让 func 为 this 值。
2. 如果 func 是一个对象 ,func 具有 [[SourceText]] 内部槽,func .[[SourceText]] 是
Unicode 代码点的序列,并且 HostHasSourceTextAvailable (func )
为 true ,则
a. 返回 CodePointsToString (func .[[SourceText]] )。
3. 如果 func 是一个 内置函数对象 ,返回一个
实现定义 的 func
的字符串源代码表示。表示必须具有 NativeFunction 的语法。此外,如果
func 具有 [[InitialName]] 内部槽,并且 func .[[InitialName]] 是一个字符串 ,则返回字符串中将匹配
NativeFunctionAccessor opt
的部分必须是 func .[[InitialName]] 的值。
4. 如果 func 是一个对象 并且 IsCallable (func ) 为
true ,返回一个 实现定义 的 func
的字符串源代码表示。表示必须具有 NativeFunction 的语法。
5. 抛出一个 TypeError 异常。
NativeFunction
:
function
NativeFunctionAccessor opt
PropertyName [~Yield,
~Await] opt
(
FormalParameters [~Yield,
~Await]
)
{
[
native
code
]
}
NativeFunctionAccessor
:
get
set
20.2.3.6 Function.prototype [ @@hasInstance ] ( V )
当调用此方法时,执行以下步骤:
1. 让 F 为 this 值。
2. 返回 ? OrdinaryHasInstance (F , V )。
此属性具有 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
false } 的特性。
注
这是大多数函数继承的 @@hasInstance
的默认实现。@@hasInstance
由 instanceof
运算符调用,以确定一个值是否是特定 构造函数 的实例。像这样的表达式
v instanceof F
评估为
F[@@hasInstance](v)
一个 构造函数 函数可以通过在函数上暴露一个不同的
@@hasInstance
方法来控制哪些对象被 instanceof
识别为其实例。
此属性是不可写且不可配置的,以防止可能用于全局暴露绑定函数的目标函数的篡改。
此方法的 "name" 属性的值是 "[Symbol.hasInstance]" 。
20.2.4 Function Instances
每个函数实例都是一个 ECMAScript 函数对象 ,并且具有表
30 中列出的内部插槽。使用Function.prototype.bind
方法(20.2.3.2) 创建的函数对象 具有表
31 中列出的内部插槽。
函数实例具有以下属性:
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
可以用作构造函数 的函数实例具有一个"prototype" 属性。每当创建这样的函数实例时,另一个普通对象 也被创建,并作为该函数的"prototype" 属性的初始值。除非另有规定,否则"prototype" 属性的值用于初始化当该函数作为构造函数 调用时创建的对象的[[Prototype]] 内部槽。
此属性的特性为 { [[Writable]] :true ,[[Enumerable]] :false ,[[Configurable]] :false }。
注
使用Function.prototype.bind
创建的函数对象 ,或者通过求值方法定义 (不是生成器方法 或异步生成器方法 ),或箭头函数 ,没有"prototype" 属性。
20.2.5 HostHasSourceTextAvailable ( func )
主定义 的抽象操作 HostHasSourceTextAvailable 接受参数
func (一个函数对象 ),并返回一个布尔值。它允许主环境 阻止提供 func 的源代码文本。
HostHasSourceTextAvailable 的实现必须符合以下要求:
对于其参数必须是确定性的。每次使用特定的 func 作为参数调用它时,它必须返回相同的结果。
HostHasSourceTextAvailable 的默认实现是返回true 。
20.3 Boolean 对象
20.3.1 Boolean 构造函数
Boolean constructor :
是 %Boolean% 。
是 "Boolean" 属性的初始值 全局对象 。
当作为 构造函数 调用时,创建并初始化一个新的 Boolean 对象。
当作为函数调用而不是 构造函数 时执行类型转换。
可以作为类定义的 extends
子句的值使用。打算继承指定 Boolean 行为的子类 构造函数 必须包含对 Boolean
constructor 的 super
调用,以使用
[[BooleanData]] 内部插槽创建和初始化子类实例。
20.3.1.1 Boolean ( value )
调用此函数时执行以下步骤:
1. 让 b 是 ToBoolean (value )。
2. 如果 NewTarget 是 undefined ,返回 b 。
3. 让 O 是 ? OrdinaryCreateFromConstructor (NewTarget,
"%Boolean.prototype%" , « [[BooleanData]] »)。
4. 设置 O .[[BooleanData]] 为
b 。
5. 返回 O 。
20.3.2 Boolean 构造函数的属性
Boolean constructor :
20.3.2.1 Boolean.prototype
Boolean.prototype
的初始值是 Boolean
原型对象 。
此属性的特性为 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
false }。
20.3.3 Boolean 原型对象的属性
Boolean 原型对象 :
是 %Boolean.prototype% 。
是一个 普通对象 。
它本身是一个 Boolean 对象;它有一个 [[BooleanData]] 内部插槽,值为 false 。
有一个 [[Prototype]] 内部插槽,其值为 %Object.prototype% 。
20.3.3.1 Boolean.prototype.constructor
Boolean.prototype.constructor
的初始值是 %Boolean% 。
20.3.3.2 Boolean.prototype.toString ( )
调用此方法时,执行以下步骤:
1. 令 b 为 ? ThisBooleanValue (this
值)。
2. 如果 b 是 true ,返回
"true" ;否则返回 "false" 。
20.3.3.3 Boolean.prototype.valueOf ( )
调用此方法时,执行以下步骤:
1. 返回 ? ThisBooleanValue (this
值)。
20.3.3.3.1 ThisBooleanValue ( value )
抽象操作 ThisBooleanValue 接受参数 value (一个 ECMAScript
语言值 )并返回一个 Boolean 或者抛出一个 完成记录 。调用时执行以下步骤:
1. 如果 value 是一个
Boolean ,返回 value 。
2. 如果 value 是一个对象 并且
value 有一个 [[BooleanData]] 内部插槽,那么:
a. 令 b 为 value .[[BooleanData]] 。
b. 断言 :b 是一个
Boolean 。
c. 返回 b 。
3. 抛出一个 TypeError 异常。
20.3.4 Boolean 实例的属性
Boolean 实例是从 Boolean
原型对象 继承属性的 普通对象 。Boolean 实例有一个 [[BooleanData]] 内部插槽。[[BooleanData]] 内部插槽是此 Boolean 对象所代表的
Boolean 值。
20.4 Symbol 对象
20.4.1 Symbol 构造器
Symbol 构造器 :
是 %Symbol% 。
是 全局对象 的 "Symbol"
属性的初始值。
当作为函数调用时,返回一个新的 Symbol 值。
不打算与 new
操作符一起使用。
不打算被子类化。
可以用作类定义的 extends
子句的值,但对其进行 super
调用将引发异常。
20.4.1.1 Symbol ( [ description ] )
调用此函数时执行以下步骤:
1. 如果 NewTarget 不是 undefined ,则抛出
TypeError 异常。
2. 如果 description 是 undefined ,则令
descString 为 undefined 。
3. 否则,令 descString 为 ? ToString (description )。
4. 返回一个新的 Symbol,其 [[Description]] 是
descString 。
20.4.2 Symbol 构造器的属性
Symbol 构造器 :
20.4.2.1 Symbol.asyncIterator
Symbol.asyncIterator
的初始值是知名符号 @@asyncIterator (表 1 )。
此属性具有 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
false } 的属性。
20.4.2.2 Symbol.for ( key )
调用此函数时执行以下步骤:
1. 令 stringKey 为 ? ToString (key )。
2. 对于 GlobalSymbolRegistry 列表 中的每个元素
e ,执行
a. 如果 SameValue (e .[[Key]] , stringKey ) 为 true ,则返回
e .[[Symbol]] 。
3. 断言 : GlobalSymbolRegistry 当前不包含
stringKey 的条目。
4. 令 newSymbol 为一个新的 Symbol,其 [[Description]] 是 stringKey 。
5. 将 { [[Key]] : stringKey , [[Symbol]] : newSymbol } 记录附加到 GlobalSymbolRegistry 列表 中。
6. 返回 newSymbol 。
GlobalSymbolRegistry 是一个全局可用的仅追加的 列表 。它由所有
域 共享。在任何
ECMAScript 代码评估之前,它被初始化为空的 列表 。GlobalSymbolRegistry
的元素是具有 记录 结构的
记录 ,如 表 60 中定义。
表 60: GlobalSymbolRegistry 记录 字段
字段名称
值
用途
[[Key]]
一个字符串
用于全局标识符号的字符串键。
[[Symbol]]
一个符号
可以从任何 域 检索到的符号。
20.4.2.3 Symbol.hasInstance
Symbol.hasInstance
的初始值是知名符号 @@hasInstance (表 1 )。
此属性具有 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
false } 的属性。
20.4.2.4 Symbol.isConcatSpreadable
Symbol.isConcatSpreadable
的初始值是知名符号 @@isConcatSpreadable (表 1 )。
此属性具有 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
false } 的属性。
20.4.2.5 Symbol.iterator
Symbol.iterator
的初始值是知名符号 @@iterator (表 1 )。
此属性具有 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
false } 的属性。
20.4.2.6 Symbol.keyFor ( sym )
调用此函数时执行以下步骤:
1. 如果 sym 不是一个符号 ,则抛出
TypeError 异常。
2. 返回 KeyForSymbol (sym )。
20.4.2.7 Symbol.match
Symbol.match
的初始值是知名符号 @@match (表 1 )。
此属性具有 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
false } 的属性。
20.4.2.8 Symbol.matchAll
Symbol.matchAll
的初始值是知名符号 @@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
的初始值是知名符号 @@replace (表 1 )。
此属性具有 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
false } 的属性。
20.4.2.11 Symbol.search
Symbol.search
的初始值是知名符号 @@search (表 1 )。
此属性具有 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
false } 的属性。
20.4.2.12 Symbol.species
Symbol.species
的初始值是知名符号 @@species (表 1 )。
此属性具有 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
false } 的属性。
20.4.2.13 Symbol.split
Symbol.split
的初始值是知名符号 @@split (表 1 )。
此属性具有 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
false } 的属性。
20.4.2.14 Symbol.toPrimitive
Symbol.toPrimitive
的初始值是知名符号 @@toPrimitive (表 1 )。
此属性具有 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
false } 的属性。
20.4.2.15 Symbol.toStringTag
Symbol.toStringTag
的初始值是知名符号 @@toStringTag (表 1 )。
此属性具有 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
false } 的属性。
20.4.2.16 Symbol.unscopables
Symbol.unscopables
的初始值是知名符号 @@unscopables (表 1 )。
此属性具有 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
false } 的属性。
20.4.3 Symbol 原型对象的属性
Symbol 原型对象 :
20.4.3.1 Symbol.prototype.constructor
Symbol.prototype.constructor
的初始值是 %Symbol% 。
20.4.3.2 get Symbol.prototype.description
Symbol.prototype.description
是一个 访问器属性 ,其 set 访问器函数为
undefined 。其 get 访问器函数在调用时执行以下步骤:
1. 令 s 为 this 值。
2. 令 sym 为 ? ThisSymbolValue (s )。
3. 返回 sym .[[Description]] 。
20.4.3.3 Symbol.prototype.toString ( )
调用此方法时执行以下步骤:
1. 令 sym 为 ? ThisSymbolValue (this
值)。
2. 返回 SymbolDescriptiveString (sym )。
20.4.3.3.1 SymbolDescriptiveString ( sym )
抽象操作 SymbolDescriptiveString 接受参数 sym (一个符号)并返回一个字符串。调用时执行以下步骤:
1. 令 desc 为 sym 的 [[Description]] 值。
2. 如果 desc 是 undefined ,则将
desc 设置为空字符串。
3. 断言 : desc 是一个字符串 。
4. 返回 字符串连接
"Symbol(" , desc , 和 ")" 。
20.4.3.4 Symbol.prototype.valueOf ( )
调用此方法时执行以下步骤:
1. 返回 ? ThisSymbolValue (this
值)。
20.4.3.4.1 ThisSymbolValue ( value )
抽象操作 ThisSymbolValue 接受参数 value (一个 ECMAScript
语言值 )并返回一个包含符号的 正常完成 或一个包含
TypeError 异常的 抛出完成 。调用时执行以下步骤:
1. 如果 value 是一个符号 ,则返回
value 。
2. 如果 value 是一个对象 并且
value 具有 [[SymbolData]] 内部插槽,则
a. 令 s 为 value .[[SymbolData]] 。
b. 断言 : s 是一个符号 。
c. 返回 s 。
3. 抛出 TypeError 异常。
20.4.3.5 Symbol.prototype [ @@toPrimitive ] ( hint )
此方法由 ECMAScript 语言操作符调用,以将 Symbol 对象转换为原始值。
调用时执行以下步骤:
1. 返回 ? ThisSymbolValue (this
值)。
注
此属性具有 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
true } 的属性。
此方法的 "name" 属性的值为 "[Symbol.toPrimitive]" 。
20.4.3.6 Symbol.prototype [ @@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 (一个符号)并返回一个字符串或 undefined 。如果 sym 存在于
GlobalSymbolRegistry 中(见 20.4.2.2 ),则返回用于注册 sym
的字符串。调用时执行以下步骤:
1. 对于 GlobalSymbolRegistry 列表 中的每个元素
e ,执行
a. 如果 SameValue (e .[[Symbol]] , sym ) 为 true ,则返回 e .[[Key]] 。
2. 断言 : GlobalSymbolRegistry 当前不包含
sym 的条目。
3. 返回 undefined 。
20.5 Error 对象
Error 对象的实例在运行时错误发生时作为异常被抛出。Error 对象也可以作为用户定义异常类的基对象。
当 ECMAScript 实现检测到运行时错误时,它会抛出一个由 20.5.5 中定义的
NativeError 对象的新实例或由 20.5.7 中定义的 AggregateError
对象的新实例。这些对象的结构如下所述,不同之处仅在于使用的名称作为构造器名称,而不是 NativeError ,在原型对象的 "name"
属性、在原型对象的实现定义的 "message" 属性和在 AggregateError 对象的特定 "errors" 属性的存在。
20.5.1 Error 构造器
Error 构造器 :
是 %Error% 。
是 全局对象 的 "Error"
属性的初始值。
在作为函数调用而不是作为 构造器 调用时创建并初始化一个新的 Error 对象。因此,函数调用
Error(…)
等同于对象创建表达式 new Error(…)
,使用相同的参数。
可以用作类定义的 extends
子句的值。打算继承指定 Error 行为的子类 构造器 必须包含对 Error 构造器 的
super
调用,以使用 [[ErrorData]] 内部插槽创建并初始化子类实例。
20.5.1.1 Error ( message [ , options ] )
调用此函数时执行以下步骤:
1. 如果 NewTarget 是 undefined ,则令
newTarget 为 活动函数对象 ;否则令
newTarget 为 NewTarget。
2. 令 O 为 ? OrdinaryCreateFromConstructor (newTarget ,
"%Error.prototype%" , « [[ErrorData]] »)。
3. 如果 message 不是 undefined ,则
a. 令 msg 为 ? ToString (message )。
b. 执行 CreateNonEnumerableDataPropertyOrThrow (O ,
"message" , msg )。
4. 执行 ? InstallErrorCause (O , options )。
5. 返回 O 。
20.5.2 Error 构造器的属性
Error 构造器 :
20.5.2.1 Error.prototype
Error.prototype
的初始值是 Error
原型对象 。
此属性具有 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
false } 的属性。
20.5.3 Error 原型对象的属性
Error 原型对象 :
是 %Error.prototype% 。
是一个 普通对象 。
不是 Error 实例,并且没有 [[ErrorData]] 内部插槽。
有一个 [[Prototype]] 内部插槽,其值是 %Object.prototype% 。
20.5.3.1 Error.prototype.constructor
Error.prototype.constructor
的初始值是 %Error% 。
20.5.3.2 Error.prototype.message
Error.prototype.message
的初始值是空字符串。
20.5.3.3 Error.prototype.name
Error.prototype.name
的初始值是 "Error" 。
20.5.3.4 Error.prototype.toString ( )
调用此方法时执行以下步骤:
1. 令 O 为 this 值。
2. 如果 O 不是对象 ,抛出一个
TypeError 异常。
3. 令 name 为 ? Get (O ,
"name" )。
4. 如果 name 是 undefined ,设置
name 为 "Error" ;否则设置 name 为 ? ToString (name )。
5. 令 msg 为 ? Get (O ,
"message" )。
6. 如果 msg 是 undefined ,设置
msg 为空字符串;否则设置 msg 为 ? ToString (msg )。
7. 如果 name 是空字符串,返回 msg 。
8. 如果 msg 是空字符串,返回 name 。
9. 返回 字符串连接 name 、代码单元
0x003A(冒号)、代码单元 0x0020(空格)和 msg 。
20.5.4 Error 实例的属性
Error 实例是 普通对象 ,继承自 Error 原型对象
并具有一个 [[ErrorData]] 内部插槽,其值为 undefined 。[[ErrorData]] 的唯一指定用途是在 Object.prototype.toString
中识别
Error、AggregateError 和 NativeError 实例。
20.5.5 本标准中使用的本机错误类型
当检测到运行时错误时,会抛出一个由以下 NativeError 对象之一或 AggregateError 对象的新实例。所有 NativeError
对象共享相同的结构,如 20.5.6 中所述。
20.5.5.1 EvalError
EvalError 构造器 是 %EvalError% 。
此异常当前未在本规范中使用。为了与本规范的先前版本兼容,此对象仍然保留。
20.5.5.2 RangeError
RangeError 构造器 是 %RangeError% 。
表示不在允许值的集合或范围内的值。
20.5.5.3 ReferenceError
ReferenceError 构造器 是 %ReferenceError% 。
表示检测到无效引用。
20.5.5.4 SyntaxError
SyntaxError 构造器 是 %SyntaxError% 。
表示发生了解析错误。
20.5.5.5 TypeError
TypeError 构造器 是 %TypeError% 。
当没有其他 NativeError 对象适合表示失败原因时,TypeError 用于表示操作失败。
20.5.5.6 URIError
URIError 构造器 是 %URIError% 。
表示全局 URI 处理函数之一的使用方式与其定义不兼容。
20.5.6 NativeError 对象结构
当 ECMAScript 实现检测到运行时错误时,它会抛出一个由 20.5.5 中定义的
NativeError 对象的新实例。每个这些对象的结构如下所述,不同之处仅在于使用的名称作为构造器名称,而不是 NativeError ,在原型对象的
"name" 属性和在实现定义的 "message" 属性中。
对于每个错误对象,定义中的 NativeError 引用应替换为 20.5.5
中适当的错误对象名称。
20.5.6.1 NativeError 构造器
每个 NativeError 构造器 :
在作为函数调用而不是作为 构造器 调用时创建并初始化一个新的 NativeError
对象。对象作为函数调用等同于作为构造器调用具有相同参数。因此,函数调用 NativeError (…)
等同于对象创建表达式
new NativeError (…)
具有相同的参数。
可以用作类定义的 extends
子句的值。打算继承指定 NativeError 行为的子类 构造器 必须包含对
NativeError 构造器 的 super
调用,以使用 [[ErrorData]] 内部插槽创建并初始化子类实例。
20.5.6.1.1 NativeError ( message [ ,
options ] )
调用每个 NativeError 函数时执行以下步骤:
1. 如果 NewTarget 是 undefined ,则令
newTarget 为 活动函数对象 ;否则令
newTarget 为 NewTarget。
2. 令
O 为 ? OrdinaryCreateFromConstructor (newTarget ,
"%NativeError .prototype%"
, « [[ErrorData]] »)。
3. 如果 message 不是 undefined ,则
a. 令 msg 为 ? ToString (message )。
b. 执行 CreateNonEnumerableDataPropertyOrThrow (O ,
"message" , msg )。
4. 执行 ? InstallErrorCause (O , options )。
5. 返回 O 。
在步骤 2
中传递的字符串的实际值是
"%EvalError.prototype%" 、"%RangeError.prototype%" 、"%ReferenceError.prototype%" 、"%SyntaxError.prototype%" 、"%TypeError.prototype%"
或 "%URIError.prototype%" ,对应于定义的 NativeError 构造器 。
20.5.6.2 NativeError 构造器的属性
每个 NativeError 构造器 :
有一个 [[Prototype]] 内部插槽,其值是 %Error% 。
有一个 "name" 属性,其值是字符串值 "NativeError " 。
具有以下属性:
20.5.6.2.1 NativeError .prototype
NativeError .prototype
的初始值是一个 NativeError 原型对象(20.5.6.3 )。每个
NativeError 构造器 有一个独特的原型对象。
此属性具有 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] : false } 的属性。
20.5.6.3 NativeError 原型对象的属性
每个 NativeError 原型对象 :
20.5.6.3.1 NativeError .prototype.constructor
给定 NativeError 的原型的 "constructor" 属性的初始值是该 NativeError
构造器 本身。
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
原型对象并具有一个 [[ErrorData]] 内部插槽,其值为 undefined 。[[ErrorData]] 的唯一指定用途是在 Object.prototype.toString
中识别
Error、AggregateError 或 NativeError 实例。
20.5.7 AggregateError 对象
20.5.7.1 AggregateError 构造器
AggregateError 构造器 :
是 %AggregateError% 。
是 全局对象 的
"AggregateError" 属性的初始值。
在作为函数调用而不是作为 构造器 调用时创建并初始化一个新的 AggregateError
对象。因此,函数调用 AggregateError(…)
等同于对象创建表达式 new AggregateError(…)
,使用相同的参数。
可以用作类定义的 extends
子句的值。打算继承指定 AggregateError 行为的子类 构造器 必须包含对 AggregateError
构造器 的 super
调用,以使用 [[ErrorData]] 内部插槽创建并初始化子类实例。
20.5.7.1.1 AggregateError ( errors , message [ ,
options ] )
调用此函数时执行以下步骤:
1. 如果 NewTarget 是 undefined ,则令
newTarget 为 活动函数对象 ;否则令
newTarget 为 NewTarget。
2. 令 O 为 ? OrdinaryCreateFromConstructor (newTarget ,
"%AggregateError.prototype%" , « [[ErrorData]] »)。
3. 如果 message 不是 undefined ,则
a. 令 msg 为 ? ToString (message )。
b. 执行 CreateNonEnumerableDataPropertyOrThrow (O ,
"message" , msg )。
4. 执行 ? InstallErrorCause (O , options )。
5. 令 errorsList 为 ? IteratorToList (? GetIterator (errors , sync ))。
6. 执行 ! DefinePropertyOrThrow (O ,
"errors" , PropertyDescriptor { [[Configurable]] :
true , [[Enumerable]] : false , [[Writable]] : true , [[Value]] :
CreateArrayFromList (errorsList ) })。
7. 返回 O 。
20.5.7.2 AggregateError 构造器的属性
AggregateError 构造器 :
有一个 [[Prototype]] 内部插槽,其值是 %Error% 。
具有以下属性:
20.5.7.2.1 AggregateError.prototype
AggregateError.prototype
的初始值是 %AggregateError.prototype% 。
此属性具有 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] : false } 的属性。
20.5.7.3 AggregateError 原型对象的属性
AggregateError 原型对象 :
是 %AggregateError.prototype% 。
是一个 普通对象 。
不是 Error 实例或 AggregateError 实例,并且没有 [[ErrorData]] 内部插槽。
有一个 [[Prototype]] 内部插槽,其值是 %Error.prototype% 。
20.5.7.3.1 AggregateError.prototype.constructor
AggregateError.prototype.constructor
的初始值是 %AggregateError% 。
20.5.7.3.2 AggregateError.prototype.message
AggregateError.prototype.message
的初始值是空字符串。
20.5.7.3.3 AggregateError.prototype.name
AggregateError.prototype.name
的初始值是 "AggregateError" 。
20.5.7.4 AggregateError 实例的属性
AggregateError 实例是 普通对象 ,继承自其 AggregateError
原型对象 并具有一个 [[ErrorData]] 内部插槽,其值为
undefined 。[[ErrorData]] 的唯一指定用途是在
Object.prototype.toString
中识别 Error、AggregateError 或 NativeError 实例。
20.5.8 Error 对象的抽象操作
20.5.8.1 InstallErrorCause ( O , options )
抽象操作 InstallErrorCause 接受参数 O (一个对象)和 options (一个 ECMAScript 语言值 ),返回
包含
unused 的正常完成或 抛出完成 。它用于在
options 上存在 "cause" 属性时在 O 上创建 "cause"
属性。调用时执行以下步骤:
1. 如果 options 是对象 并且
? HasProperty (options , "cause" ) 为
true ,则
a. 令 cause 为 ? Get (options , "cause" )。
b. 执行 CreateNonEnumerableDataPropertyOrThrow (O ,
"cause" , cause )。
2. 返回 unused 。
21 数字和日期
21.1 Number Objects
21.1.1 The Number Constructor
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 Properties of the Number Constructor
Number 构造函数 :
21.1.2.1 Number.EPSILON
Number.EPSILON
的值是 Number 值 ,表示 1 与大于 1 的最小值之间的差值,约为
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 )
当被调用时,此函数执行以下步骤:
返回 IsIntegralNumber (number )。
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 是 "安全整数 " 如果且仅如果 n 的 Number
值 不与任何其他整数的 Number 值 相同。
当被调用时,此函数执行以下步骤:
如果 IsIntegralNumber (number )
是 true ,则
如果 abs (ℝ (number )) ≤ 2** 53 - 1,返回 true 。
返回 false 。
21.1.2.6 Number.MAX_SAFE_INTEGER
注
由于 IEEE 754-2019 的精度限制所需的舍入行为,每个大于
Number.MAX_SAFE_INTEGER
的整数的 Number 值 与至少另一个整数的 Number
值 相同。因此,这些大幅度整数不是 安全整数 ,不能保证精确表示为 Number
值,甚至不能保证相互区分。例如,9007199254740992
和 9007199254740993
都评估为 Number 值
9007199254740992 𝔽 。
Number.MAX_SAFE_INTEGER
的值为 9007199254740991 𝔽 (𝔽 (2** 53 - 1))。
此属性具有 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
false } 的属性。
21.1.2.7 Number.MAX_VALUE
Number.MAX_VALUE
的值是 有限 值中的最大正值 Number 类型 ,约为
1.7976931348623157 × 10** 308 。
此属性具有 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
false } 的属性。
21.1.2.8 Number.MIN_SAFE_INTEGER
注
由于 IEEE 754-2019 的精度限制所需的舍入行为,每个小于
Number.MIN_SAFE_INTEGER
的整数的 Number 值 与至少另一个整数的 Number
值 相同。因此,这些大幅度整数不是 安全整数 ,不能保证精确表示为 Number
值,甚至不能保证相互区分。例如,-9007199254740992
和 -9007199254740993
都评估为 Number 值
-9007199254740992 𝔽 。
Number.MIN_SAFE_INTEGER
的值为 -9007199254740991 𝔽 (𝔽 (-(2** 53 - 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 )
Number.parseFloat
属性的初始值是 %parseFloat% 。
21.1.2.13 Number.parseInt ( string , radix )
Number.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 Properties of the Number Prototype Object
Number 原型对象 :
是 %Number.prototype% 。
是一个 普通对象 。
它本身是一个 Number 对象;它有一个 [[NumberData]] 内部槽,值为 +0 𝔽 。
有一个 [[Prototype]] 内部槽,其值为 %Object.prototype% 。
除非明确声明,否则以下定义的 Number 原型对象的方法不是通用的,传递给它们的 this 值必须是 Number 值或带有已初始化为 Number 值的 [[NumberData]] 内部槽的对象。
规范中方法中的 "this Number value" 术语是指调用抽象操作 ThisNumberValue ,传递方法调用的
this 值作为参数,返回的结果。
21.1.3.1 Number.prototype.constructor
Number.prototype.constructor
的初始值是 %Number% 。
21.1.3.2 Number.prototype.toExponential ( fractionDigits )
此方法返回一个字符串,其中包含此 Number 值,以十进制指数表示法表示,小数点前一位数字,小数点后 fractionDigits 位数字。如果
fractionDigits 为 undefined ,则包括所有必要的有效数字,以唯一地指定 Number(就像在 ToString
中一样,只不过在这种情况下,Number 始终以指数表示法输出)。
当被调用时,它执行以下步骤:
令 x 为 ? ThisNumberValue (this
值)。
令 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 为 整数 ,使得 10** f ≤ n < 10**( f + 1) 且
n × 10**( e -
f ) - x 尽可能接近零。如果有两个这样的
e 和 n 组合,则选择使 n × 10**( e - f ) 更大的组合。
否则,
令 e 、n 和
ff 为 整数 ,使得 ff ≥ 0,10** ff ≤ n < 10**( ff + 1) ,𝔽 (n × 10**( e - 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,10** f ≤ n < 10**( f + 1) ,𝔽 (n × 10**( e - f ) ) 为 𝔽 (x ),并且 f
尽可能小。如果 n 有多个可能的值,选择 n 的值,使得 𝔽 (n × 10**( e - f ) ) 最接近 𝔽 (x )。如果有两个这样的
n 的可能值,选择偶数的那个。
21.1.3.3 Number.prototype.toFixed ( fractionDigits )
注 1
此方法返回一个字符串,其中包含此 Number 值,以十进制定点表示法表示,小数点后 fractionDigits 位数字。如果 fractionDigits
为 undefined ,则假定为 0。
当被调用时,它执行以下步骤:
令 x 为 ? ThisNumberValue (this
值)。
令 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 ≥ 10** 21 ,则
令 m 为 ! ToString (𝔽 (x ))。
否则,
令 n 为一个 整数 ,使得 n / 10** f - 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
值)。
如果 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 为 整数 ,使得 10**( p - 1) ≤
n < 10** p 且 n ×
10**( e - p + 1) - x 尽可能接近零。如果有两个这样的 e 和 n 组合,则选择使
n × 10**( e - p +
1) 更大的组合。
令 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 应为 整数 Number 值,范围在 包括区间
2 𝔽 到 36 𝔽 之间。如果 radix 为
undefined ,则 10 𝔽 被用作 radix 的值。
当被调用时,此方法执行以下步骤:
令 x 为 ? ThisNumberValue (this
值)。
如果 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
值)。
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 )
当调用时,此函数执行以下步骤:
1. 如果 NewTarget 不是 undefined ,抛出
TypeError 异常。
2. 令 prim 为 ? ToPrimitive (value ,
number )。
3. 如果 prim 是一个
Number ,返回 ? NumberToBigInt (prim )。
4. 否则,返回 ? ToBigInt (prim )。
21.2.1.1.1 NumberToBigInt ( number )
抽象操作 NumberToBigInt 接受参数 number (一个 Number),并返回
包含 一个 BigInt
的正常完成记录或一个
抛出完成记录 。它在被调用时执行以下步骤:
1. 如果 IsIntegralNumber (number )
是 false ,抛出一个 RangeError 异常。
2. 返回 ℤ (ℝ (number ))。
21.2.2 BigInt 构造函数的属性
BigInt 构造函数 :
21.2.2.1 BigInt.asIntN ( bits , bigint )
此函数在调用时执行以下步骤:
1. 将 bits 设置为 ? ToIndex (bits )。
2. 将 bigint 设置为 ? ToBigInt (bigint )。
3. 令 mod 为 ℝ (bigint ) 模
2** bits 。
4. 如果 mod ≥ 2**( bits - 1) ,
返回
ℤ (mod - 2** bits );否则,返回 ℤ (mod )。
21.2.2.2 BigInt.asUintN ( bits , bigint )
此函数在调用时执行以下步骤:
1. 将 bits 设置为 ? ToIndex (bits )。
2. 将 bigint 设置为 ? ToBigInt (bigint )。
3. 返回 ℤ (ℝ (bigint )
模
2** bits )。
21.2.2.3 BigInt.prototype
BigInt.prototype
的初始值为 BigInt
原型对象 。
此属性具有 { [[Writable]] : false ,
[[Enumerable]] : false , [[Configurable]] :
false } 的属性。
21.2.3 BigInt 原型对象的属性
BigInt 原型对象 :
方法规范中的短语“这个 BigInt 值”指的是通过调用抽象操作 ThisBigIntValue 传递给方法调用的
this 值的结果。
21.2.3.1 BigInt.prototype.constructor
BigInt.prototype.constructor
的初始值为 %BigInt% 。
21.2.3.2 BigInt.prototype.toLocaleString ( [ reserved1 [ ,
reserved2 ] ] )
包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范实现此方法。如果 ECMAScript 实现不包含
ECMA-402 API,则使用以下方法规范:
此方法生成一个字符串值,该值根据 宿主环境 当前区域设置的约定表示此 BigInt 值。此方法是
实现定义的 ,允许但不鼓励它返回与
toString
相同的内容。
此方法的可选参数的含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得将这些参数位置用于其他任何用途。
21.2.3.3 BigInt.prototype.toString ( [ radix ] )
注
可选的 radix 应该是 整数 值,范围为
2 到 36 的
包含区间 𝔽 。如果 radix 是
undefined ,则将 10 𝔽 用作 radix 的值。
此方法在调用时执行以下步骤:
1. 令 x 为 ? ThisBigIntValue (this
值)。
2. 如果 radix 是 undefined ,令
radixMV 为 10。
3. 否则,令 radixMV 为 ? ToIntegerOrInfinity (radix )。
4. 如果 radixMV 不在 2 到 36 的
包含区间 内,抛出 RangeError 异常。
5. 返回 BigInt::toString (x ,
radixMV )。
此方法不是通用的;如果其 this 值 不是
BigInt 或 BigInt 对象,则抛出 TypeError 异常。因此,它不能转移到其他类型的对象中用作方法。
21.2.3.4 BigInt.prototype.valueOf ( )
1. 返回 ? ThisBigIntValue (this
值)。
21.2.3.4.1 ThisBigIntValue ( value )
抽象操作 ThisBigIntValue 接受参数 value (一个 ECMAScript
语言值 )并返回
包含 一个 BigInt
的正常完成记录或一个
抛出完成记录 。它在被调用时执行以下步骤:
1. 如果 value 是一个
BigInt ,返回 value 。
2. 如果 value 是一个对象
并且 value 具有 [[BigIntData]] 内部槽,则
a. 断言 :value .[[BigIntData]] 是一个
BigInt 。
b. 返回 value .[[BigIntData]] 。
3. 抛出一个 TypeError 异常。
21.2.3.5 BigInt.prototype [ @@toStringTag ]
@@toStringTag 属性的初始值是字符串
"BigInt" 。
此属性具有 { [[Writable]] : false ,
[[Enumerable]] : false , [[Configurable]] :
true } 的属性。
21.2.4 BigInt 实例的属性
BigInt 实例是 普通对象 ,它们继承自 BigInt
原型对象 的属性。BigInt 实例也有一个 [[BigIntData]] 内部槽。[[BigIntData]] 内部槽是此 BigInt 对象表示的 BigInt 值。
21.3 数学对象
数学对象:
是 %Math% .
是 "Math" 属性在 全局对象 的初始值.
是一个 普通对象 .
有一个 [[Prototype]] 内部槽,其值为 %Object.prototype% .
不是一个 函数对象 .
没有 [[Construct]] 内部方法;它不能被 构造器 用 new
操作符使用.
没有 [[Call]] 内部方法;它不能被调用为函数.
注
在这个规范中,“Number 值 x ”这个短语有一个在
6.1.6.1
中定义的技术含义.
21.3.1 Math 对象的值属性
21.3.1.1 Math.E
自然对数的底数 Number 值 e ,约等于
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
1/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 [ @@toStringTag ]
@@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
、sqrt
、tan
和 tanh
的行为在此并未精确指定,只是要求对于某些有意义的边界值给出特定结果。对于其他参数值,这些函数旨在计算熟悉的数学函数的近似值,但在选择近似算法时允许有一定的自由度。总体意图是实现者应该能够在给定硬件平台上的
ECMAScript 中使用同样适用于该平台上的 C 程序员的数学库。
虽然算法的选择留给实现决定,但建议(但本标准未规定)实现使用 IEEE 754-2019 算术的
fdlibm
,这是 Sun Microsystems 提供的自由分发的数学库(http://www.netlib.org/fdlibm )。
21.3.2.1 Math.abs ( x )
该函数返回 x 的绝对值;结果与 x 具有相同的幅度,但符号为正。
调用时执行以下步骤:
1. 令 n 为 ? ToNumber (x ).
2. 如果 n 是 NaN ,返回
NaN 。
3. 如果 n 是 -0 𝔽 ,返回
+0 𝔽 。
4. 如果 n 是 -∞ 𝔽 ,返回
+∞ 𝔽 。
5. 如果 n < -0 𝔽 ,返回
-n 。
6. 返回 n 。
21.3.2.2 Math.acos ( x )
该函数返回 x 的反余弦值。结果以弧度表示,位于从 +0 𝔽 到 𝔽 (π) 的包含区间 内。
调用时执行以下步骤:
1. 令 n 为 ? ToNumber (x ).
2. 如果 n 是 NaN ,n >
1 𝔽 ,或 n < -1 𝔽 ,返回
NaN 。
3. 如果 n 是 1 𝔽 ,返回
+0 𝔽 。
4. 返回一个 实现近似的
Number 值,表示 ℝ (n ) 的反余弦结果。
21.3.2.3 Math.acosh ( x )
该函数返回 x 的反双曲余弦值。
调用时执行以下步骤:
1. 令 n 为 ? ToNumber (x ).
2. 如果 n 是 NaN 或
+∞ 𝔽 ,返回 n 。
3. 如果 n 是 1 𝔽 ,返回
+0 𝔽 。
4. 如果 n < 1 𝔽 ,返回
NaN 。
5. 返回一个 实现近似的
Number 值,表示 ℝ (n ) 的反双曲余弦结果。
21.3.2.4 Math.asin ( x )
该函数返回 x 的反正弦值。结果以弧度表示,位于从 𝔽 (-π / 2) 到 𝔽 (π / 2) 的包含区间 内。
调用时执行以下步骤:
1. 令 n 为 ? ToNumber (x ).
2. 如果 n 是
NaN 、+0 𝔽 或 -0 𝔽 之一,返回
n 。
3. 如果 n > 1 𝔽 或
n < -1 𝔽 ,返回 NaN 。
4. 返回一个 实现近似的
Number 值,表示 ℝ (n ) 的反正弦结果。
21.3.2.5 Math.asinh ( x )
该函数返回 x 的反双曲正弦值。
调用时执行以下步骤:
1. 令 n 为 ? ToNumber (x ).
2. 如果 n 不是 有限 或 n 是
+0 𝔽 或 -0 𝔽 之一,返回 n 。
3. 返回一个 实现近似的
Number 值,表示 ℝ (n ) 的反双曲正弦结果。
21.3.2.6 Math.atan ( x )
该函数返回 x 的反正切值。结果以弧度表示,位于从 𝔽 (-π / 2) 到 𝔽 (π / 2) 的包含区间 内。
调用时执行以下步骤:
1. 令 n 为 ? ToNumber (x ).
2. 如果 n 是
NaN 、+0 𝔽 或 -0 𝔽 之一,返回
n 。
3. 如果 n 是 +∞ 𝔽 ,返回一个
实现近似的 Number 值,表示 π /
2。
4. 如果 n 是 -∞ 𝔽 ,返回一个
实现近似的 Number 值,表示 -π /
2。
5. 返回一个 实现近似的
Number 值,表示 ℝ (n ) 的反正切结果。
21.3.2.7 Math.atanh ( x )
该函数返回 x 的反双曲正切值。
调用时执行以下步骤:
1. 令 n 为 ? ToNumber (x ).
2. 如果 n 是
NaN 、+0 𝔽 或 -0 𝔽 之一,返回
n 。
3. 如果 n > 1 𝔽 或
n < -1 𝔽 ,返回 NaN 。
4. 如果 n 是 1 𝔽 ,返回
+∞ 𝔽 。
5. 如果 n 是 -1 𝔽 ,返回
-∞ 𝔽 。
6. 返回一个 实现近似的
Number 值,表示 ℝ (n ) 的反双曲正切结果。
21.3.2.8 Math.atan2 ( y , x )
该函数返回参数 y 和 x 的商 y / x
的反正切值,其中 y 和 x 的符号用于确定结果的象限。注意,两个参数反正切函数的参数名称 y 在前,x
在后,是故意和传统的。结果以弧度表示,位于从 -π 到 +π 的包含区间 内。
调用时执行以下步骤:
1. 令 ny 为 ? ToNumber (y ).
2. 令 nx 为 ? ToNumber (x ).
3. 如果 ny 是 NaN 或 nx 是
NaN ,返回 NaN 。
4. 如果 ny 是 +∞ 𝔽 ,则
a. 如果 nx 是 +∞ 𝔽 ,返回一个
实现近似的 Number 值,表示
π / 4。
b. 如果 nx 是 -∞ 𝔽 ,返回一个
实现近似的 Number 值,表示
3π / 4。
c. 返回一个 实现近似的 Number 值,表示
π / 2。
5. 如果 ny 是 -∞ 𝔽 ,则
a. 如果 nx 是 +∞ 𝔽 ,返回一个
实现近似的 Number 值,表示
-π / 4。
b. 如果 nx 是 -∞ 𝔽 ,返回一个
实现近似的 Number 值,表示
-3π / 4。
c. 返回一个 实现近似的 Number 值,表示
-π / 2。
6. 如果 ny 是 +0 𝔽 ,则
a. 如果 nx > +0 𝔽 或
nx 是 +0 𝔽 ,返回 +0 𝔽 。
b. 返回一个 实现近似的 Number 值,表示
π。
7. 如果 ny 是 -0 𝔽 ,则
a. 如果 nx > +0 𝔽 或
nx 是 +0 𝔽 ,返回 -0 𝔽 。
b. 返回一个 实现近似的 Number 值,表示
-π。
8. 断言 :ny 是 有限的 ,且既不是
+0 𝔽 也不是 -0 𝔽 。
9. 如果 ny > +0 𝔽 ,则
a. 如果 nx 是 +∞ 𝔽 ,返回
+0 𝔽 。
b. 如果 nx 是 -∞ 𝔽 ,返回一个
实现近似的 Number 值,表示
π。
c. 如果 nx 是 +0 𝔽 或
-0 𝔽 之一,返回一个 实现近似的 Number 值,表示
π / 2。
10. 如果 ny < -0 𝔽 ,则
a. 如果 nx 是 +∞ 𝔽 ,返回
-0 𝔽 。
b. 如果 nx 是 -∞ 𝔽 ,返回一个
实现近似的 Number 值,表示
-π。
c. 如果 nx 是 +0 𝔽 或
-0 𝔽 之一,返回一个 实现近似的 Number 值,表示
-π / 2。
11. 断言 :nx 是 有限的 ,且既不是
+0 𝔽 也不是 -0 𝔽 。
12. 令 r 为 abs (ℝ (ny ) / ℝ (nx )) 的反正切值。
13. 如果 nx < -0 𝔽 ,则
a. 如果 ny > +0 𝔽 ,设置
r 为 π - r 。
b. 否则,设置 r 为 -π + r 。
14. 否则,
a. 如果 ny < -0 𝔽 ,设置
r 为 -r 。
15. 返回一个 实现近似的
Number 值,表示 r 。
21.3.2.9 Math.cbrt ( x )
此函数返回 x 的立方根。
调用时执行以下步骤:
1. 令 n 为 ? ToNumber (x ).
2. 如果 n 不是 有限的 或 n 是
+0 𝔽 或 -0 𝔽 ,返回 n 。
3. 返回一个 实现近似的
Number 值,表示 ℝ (n ) 的立方根。
21.3.2.10 Math.ceil ( x )
此函数返回不小于 x 的最小(最接近 -∞)整数 值。如果 x 已经是一个
整数 ,结果是 x 。
调用时执行以下步骤:
1. 令 n 为 ? ToNumber (x ).
2. 如果 n 不是 有限的 或 n 是
+0 𝔽 或 -0 𝔽 ,返回 n 。
3. 如果 n < -0 𝔽 且
n > -1 𝔽 ,返回 -0 𝔽 。
4. 如果 n 是 整数 ,返回
n 。
5. 返回不小于 n 的最小(最接近 -∞)整数 值。
注
Math.ceil(x)
的值与 -Math.floor(-x)
的值相同。
21.3.2.11 Math.clz32 ( x )
此函数在调用时执行以下步骤:
1. 令 n 为 ? ToUint32 (x ).
2. 令 p 为 n 的无符号 32 位二进制表示中前导零位的数量。
3. 返回 𝔽 (p ).
注
如果 n 是 +0 𝔽 或 -0 𝔽 ,此方法返回
32 𝔽 。如果 n 的 32 位二进制编码的最高有效位为 1,此方法返回
+0 𝔽 。
21.3.2.12 Math.cos ( x )
此函数返回 x 的余弦值。参数以弧度表示。
调用时执行以下步骤:
1. 令 n 为 ? ToNumber (x ).
2. 如果 n 不是 有限的 ,返回 NaN 。
3. 如果 n 是 +0 𝔽 或
-0 𝔽 ,返回 1 𝔽 。
4. 返回一个 实现近似的
Number 值,表示 ℝ (n ) 的余弦值。
21.3.2.13 Math.cosh ( x )
此函数返回 x 的双曲余弦值。
调用时执行以下步骤:
1. 令 n 为 ? ToNumber (x ).
2. 如果 n 是 NaN ,返回
NaN 。
3. 如果 n 是 +∞ 𝔽 或
-∞ 𝔽 ,返回 +∞ 𝔽 。
4. 如果 n 是 +0 𝔽 或
-0 𝔽 ,返回 1 𝔽 。
5. 返回一个 实现近似的
Number 值,表示 ℝ (n ) 的双曲余弦值。
注
Math.cosh(x)
的值与 (Math.exp(x) + Math.exp(-x)) / 2
的值相同。
21.3.2.14 Math.exp ( x )
此函数返回 x 的指数函数值(e 的 x 次幂,其中 e 是自然对数的底)。
调用时执行以下步骤:
1. 令 n 为 ? ToNumber (x ).
2. 如果 n 是 NaN 或
+∞ 𝔽 ,返回 n 。
3. 如果 n 是 +0 𝔽 或
-0 𝔽 ,返回 1 𝔽 。
4. 如果 n 是 -∞ 𝔽 ,返回
+0 𝔽 。
5. 返回一个 实现近似的
Number 值,表示 ℝ (n ) 的指数函数值。
21.3.2.15 Math.expm1 ( x )
此函数返回从 x 的指数函数值中减去 1 的结果(e 的 x 次幂,其中 e 是自然对数的底)。该结果的计算方式即使在
x 值接近 0 时也能保证准确。
调用时执行以下步骤:
1. 令 n 为 ? ToNumber (x ).
2. 如果 n 是
NaN 、+0 𝔽 、-0 𝔽 或
+∞ 𝔽 中的任意一个,返回 n 。
3. 如果 n 是 -∞ 𝔽 ,返回
-1 𝔽 。
4. 返回一个 实现近似的
Number 值,表示从 ℝ (n ) 的指数函数值中减去 1 的结果。
21.3.2.16 Math.floor ( x )
此函数返回不大于 x 的最大(最接近 +∞)整数值 。如果 x 已经是一个 整数值 ,则返回结果为 x 。
调用时执行以下步骤:
1. 令 n 为 ? ToNumber (x ).
2. 如果 n 不是 有限的 或 n 是
+0 𝔽 或 -0 𝔽 ,则返回 n 。
3. 如果 n < 1 𝔽 并且
n > +0 𝔽 ,则返回 +0 𝔽 。
4. 如果 n 是一个 整数值 ,则返回
n 。
5. 返回不大于 n 的最大(最接近 +∞)整数值 。
注
Math.floor(x)
的值与 -Math.ceil(-x)
的值相同。
21.3.2.17 Math.fround ( x )
此函数在调用时执行以下步骤:
1. 令 n 为 ? ToNumber (x ).
2. 如果 n 是 NaN ,返回
NaN 。
3. 如果 n 是
+0 𝔽 、-0 𝔽 、+∞ 𝔽
或 -∞ 𝔽 中的任意一个,则返回 n 。
4. 令 n32 为使用 roundTiesToEven 模式将 n 转换为
IEEE 754-2019 binary32 格式的结果。
5. 令 n64 为将 n32 转换为 IEEE
754-2019 binary64 格式的结果。
6. 返回与 n64 对应的 ECMAScript 数值。
21.3.2.18 Math.hypot ( ...args )
给定零个或多个参数,此函数返回其参数的平方和的平方根。
调用时执行以下步骤:
1. 令 coerced 为一个新的空的 列表 。
2. 对于 args 中的每个元素 arg ,执行
a. 令 n 为 ? ToNumber (arg ).
b. 将 n 附加到 coerced 。
3. 对于 coerced 中的每个元素 number ,执行
a. 如果 number 是 +∞ 𝔽 或
-∞ 𝔽 ,则返回 +∞ 𝔽 。
4. 令 onlyZero 为 true 。
5. 对于 coerced 中的每个元素 number ,执行
a. 如果 number 是 NaN ,则返回
NaN 。
b. 如果 number 既不是 +0 𝔽
也不是 -0 𝔽 ,则将 onlyZero 设置为 false 。
6. 如果 onlyZero 是 true ,则返回
+0 𝔽 。
7. 返回一个 实现近似的
Number 值,表示 coerced 中各元素的数学值 的平方和的平方根。
此函数的 "length" 属性为 2 𝔽 。
注
实现应注意避免在此函数以两个或更多参数调用时由于溢出和下溢导致的精度损失,这在天真的实现中容易发生。
21.3.2.19 Math.imul ( x , y )
此函数在调用时执行以下步骤:
1. 令 a 为 ℝ (? ToUint32 (x )).
2. 令 b 为 ℝ (? ToUint32 (y )).
3. 令 product 为 (a × b ) 模 2** 32 。
4. 如果 product ≥ 2** 31 ,返回 𝔽 (product - 2** 32 );否则返回 𝔽 (product )。
21.3.2.20 Math.log ( x )
此函数返回 x 的自然对数。
调用时执行以下步骤:
1. 令 n 为 ? ToNumber (x ).
2. 如果 n 是 NaN 或
+∞ 𝔽 ,返回 n 。
3. 如果 n 是 1 𝔽 ,返回
+0 𝔽 。
4. 如果 n 是 +0 𝔽 或
-0 𝔽 ,返回 -∞ 𝔽 。
5. 如果 n < -0 𝔽 ,返回
NaN 。
6. 返回 实现近似的
Number 值,表示 ℝ (n ) 的自然对数结果。
21.3.2.21 Math.log1p ( x )
此函数返回 1 + x 的自然对数。即使当 x 的值接近于零时,该结果的计算也很准确。
调用时执行以下步骤:
1. 令 n 为 ? ToNumber (x ).
2. 如果 n 是
NaN 、+0 𝔽 、-0 𝔽 或
+∞ 𝔽 中的一个,返回 n 。
3. 如果 n 是 -1 𝔽 ,返回
-∞ 𝔽 。
4. 如果 n < -1 𝔽 ,返回
NaN 。
5. 返回 实现近似的
Number 值,表示 1 + ℝ (n ) 的自然对数结果。
21.3.2.22 Math.log10 ( x )
此函数返回 x 的以 10 为底的对数。
调用时执行以下步骤:
1. 令 n 为 ? ToNumber (x ).
2. 如果 n 是 NaN 或
+∞ 𝔽 ,返回 n 。
3. 如果 n 是 1 𝔽 ,返回
+0 𝔽 。
4. 如果 n 是 +0 𝔽 或
n 是 -0 𝔽 ,返回 -∞ 𝔽 。
5. 如果 n < -0 𝔽 ,返回
NaN 。
6. 返回 实现近似的
Number 值,表示 ℝ (n ) 的以 10 为底的对数结果。
21.3.2.23 Math.log2 ( x )
此函数返回 x 的以 2 为底的对数。
调用时执行以下步骤:
1. 令 n 为 ? ToNumber (x ).
2. 如果 n 是 NaN 或 n 是
+∞ 𝔽 ,返回 n 。
3. 如果 n 是 1 𝔽 ,返回
n 。
4. 如果 n 是 +0 𝔽 或
n 是 -0 𝔽 ,返回 n 。
5. 如果 n < -0 𝔽 ,返回
n 。
6. 返回 实现近似的
Number 值,表示 ℝ (n ) 的以 2 为底的对数结果。
21.3.2.24 Math.max ( ...args )
给定零个或多个参数,此函数调用 ToNumber 在每个参数上并返回结果值中最大的一个。
调用时执行以下步骤:
1. 令 coerced 为一个新的空的 List 。
2. 对于 args 中的每个元素 arg ,执行
a. 令 n 为 ? ToNumber (arg ).
b. 将 n 附加到 coerced 。
3. 令 highest 为 -∞ 𝔽 。
4. 对于 coerced 中的每个元素 number ,执行
a. 如果 number 是 NaN ,返回
number 。
b. 如果 number 是 +0 𝔽 且
highest 是 -0 𝔽 ,将 highest 设置为
+0 𝔽 。
c. 如果 number > highest ,将
highest 设置为 number 。
5. 返回 highest 。
注
用于确定最大值的值比较是使用 IsLessThan 算法进行的,除非
+0 𝔽 被认为大于 -0 𝔽 。
此函数的 "length" 属性为 2 𝔽 。
21.3.2.25 Math.min ( ...args )
给定零个或多个参数,此函数调用 ToNumber 在每个参数上并返回结果值中最小的一个。
调用时执行以下步骤:
1. 令 coerced 为一个新的空的 List 。
2. 对于 args 中的每个元素 arg ,执行
a. 令 n 为 ? ToNumber (arg ).
b. 将 n 附加到 coerced 。
3. 令 lowest 为 +∞ 𝔽 。
4. 对于 coerced 中的每个元素 number ,执行
a. 如果 number 是 NaN ,返回
NaN 。
b. 如果 number 是 -0 𝔽 且
lowest 是 +0 𝔽 ,将 lowest 设置为
-0 𝔽 。
c. 如果 number < lowest ,将
lowest 设置为 number 。
5. 返回 lowest 。
注
用于确定最小值的值比较是使用 IsLessThan 算法进行的,除非
+0 𝔽 被认为大于 -0 𝔽 。
此函数的 "length" 属性为 2 𝔽 。
21.3.2.26 Math.pow ( base , exponent )
此函数在调用时执行以下步骤:
1. 将 base 设置为 ? ToNumber (base ).
2. 将 exponent 设置为 ? ToNumber (exponent ).
3. 返回 Number::exponentiate (base ,
exponent )。
21.3.2.27 Math.random ( )
此函数返回一个带正号的 Number 值,大于或等于 +0 𝔽 但严格小于
1 𝔽 ,在该范围内随机或伪随机地选择,使用 实现定义的 算法或策略。
为不同 realm
创建的每个 Math.random
函数必须从连续调用中产生不同的值序列。
21.3.2.28 Math.round ( x )
此函数返回最接近 x 并且是整数的 Number 值。如果两个 整数 离 x 同样近,则结果是更接近 +∞ 的
Number 值。如果 x 已经是整数,结果是 x 。
调用时执行以下步骤:
1. 令 n 为 ? ToNumber (x ).
2. 如果 n 不是 有限的 或 n 是一个 整数 ,返回 n 。
3. 如果 n < 0.5 𝔽 且
n > +0 𝔽 ,返回 +0 𝔽 。
4. 如果 n < -0 𝔽 且
n ≥ -0.5 𝔽 ,返回 -0 𝔽 。
5. 返回最接近 n 的 整数 ,在平局的情况下优先返回更接近
+∞ 的值。
注 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 𝔽 。由于计算 x + 0.5
时的内部舍入,Math.round(x)
可能与
Math.floor(x + 0.5)
的值不同。
21.3.2.29 Math.sign ( x )
此函数返回 x 的符号,指示 x 是正数、负数还是零。
调用时执行以下步骤:
1. 令 n 为 ? ToNumber (x ).
2. 如果 n 是
NaN 、+0 𝔽 或 -0 𝔽 ,返回
n 。
3. 如果 n < -0 𝔽 ,返回
-1 𝔽 。
4. 返回 1 𝔽 。
21.3.2.30 Math.sin ( x )
此函数返回 x 的正弦值。参数以弧度表示。
调用时执行以下步骤:
1. 令 n 为 ? ToNumber (x ).
2. 如果 n 是
NaN 、+0 𝔽 或 -0 𝔽 ,返回
n 。
3. 如果 n 是 +∞ 𝔽 或
n 是 -∞ 𝔽 ,返回 NaN 。
4. 返回 实现近似的
Number 值,表示 ℝ (n ) 的正弦值结果。
21.3.2.31 Math.sinh ( x )
此函数返回 x 的双曲正弦值。
调用时执行以下步骤:
1. 令 n 为 ? ToNumber (x ).
2. 如果 n 不是 有限的 或 n 是
+0 𝔽 或 n 是 -0 𝔽 ,返回
n 。
3. 返回 实现近似的
Number 值,表示 ℝ (n ) 的双曲正弦值结果。
注
Math.sinh(x)
的值与 (Math.exp(x) - Math.exp(-x)) / 2
的值相同。
21.3.2.32 Math.sqrt ( x )
此函数返回 x 的平方根。
调用时执行以下步骤:
1. 令 n 为 ? ToNumber (x ).
2. 如果 n 是
NaN 、+0 𝔽 、-0 𝔽 或
+∞ 𝔽 之一,返回 n 。
3. 如果 n < -0 𝔽 ,返回
NaN 。
4. 返回 实现近似的
Number 值,表示 ℝ (n ) 的平方根结果。
21.3.2.33 Math.tan ( x )
此函数返回 x 的正切值。参数以弧度表示。
调用时执行以下步骤:
1. 令 n 为 ? ToNumber (x ).
2. 如果 n 是
NaN 、+0 𝔽 或 -0 𝔽 之一,返回
n 。
3. 如果 n 是 +∞ 𝔽 或
-∞ 𝔽 ,返回 NaN 。
4. 返回 实现近似的
Number 值,表示 ℝ (n ) 的正切值结果。
21.3.2.34 Math.tanh ( x )
此函数返回 x 的双曲正切值。
调用时执行以下步骤:
1. 令 n 为 ? ToNumber (x ).
2. 如果 n 是
NaN 、+0 𝔽 或 -0 𝔽 之一,返回
n 。
3. 如果 n 是 +∞ 𝔽 ,返回
1 𝔽 。
4. 如果 n 是 -∞ 𝔽 ,返回
-1 𝔽 。
5. 返回 实现近似的
Number 值,表示 ℝ (n ) 的双曲正切值结果。
注
Math.tanh(x)
的值与
(Math.exp(x) - Math.exp(-x)) / (Math.exp(x) + Math.exp(-x))
的值相同。
21.3.2.35 Math.trunc ( x )
此函数返回数值 x 的整数部分,去除任何小数位。如果 x 已经是整数,结果是 x 。
调用时执行以下步骤:
1. 令 n 为 ? ToNumber (x ).
2. 如果 n 不是 有限的 或 n 是
+0 𝔽 或 n 是 -0 𝔽 ,返回
n 。
3. 如果 n < 1 𝔽 且
n > +0 𝔽 ,返回 +0 𝔽 。
4. 如果 n < -0 𝔽 且
n > -1 𝔽 ,返回 -0 𝔽 。
5. 返回最接近 n 的 整数 ,方向为
+0 𝔽 。
21.4 日期对象
21.4.1 日期对象概述和抽象操作的定义
以下 抽象操作 操作于
时间值 (定义在
21.4.1.1 中)。注意,
在每种情况下,如果这些函数的任何参数是 NaN ,结果将是 NaN 。
21.4.1.1 时间值和时间范围
ECMAScript 中的时间测量类似于 POSIX 中的时间测量,特别是在定义上共享了如下内容:采用公历日期,纪元时间为 1970 年 1 月 1 日凌晨 0 时 0 分 0 秒(UTC),并将每一天精确计为
86,400 秒(每秒包含 1000 毫秒)。
ECMAScript 的 时间值 是一个数字 ,要么是表示某个时间点的精确到毫秒的有限
整数 ,要么是表示没有特定时间点的
NaN 。时间值是 24 × 60 × 60 × 1000 = 86,400,000 的倍数(即
86,400,000 × d ,其中 d 为某个 整数 ),表示 UTC 日的开始时间点,从 纪元 起经过 d 个整天(对负
d ,则在纪元之前)。其他所有有限的时间值 t 相对于最大前置时间值 s 定义,该时间值 s
是上述倍数,并表示发生在同一天内但比 s 晚 (t - s ) 毫秒的时间点。
时间值不考虑 UTC 闰秒——不存在表示正闰秒内瞬间的时间值,并且存在表示由负闰秒从 UTC 时间线中移除的瞬间的时间值。然而,时间值的定义仍然能与 UTC
分段对齐,仅在闰秒边界处存在不连续性,且在非闰秒时段内零差异。
一个数字可以精确表示从 -9,007,199,254,740,992 到 9,007,199,254,740,992 的所有 整数 。时间值支持的范围稍小,为
-8,640,000,000,000,000 到 8,640,000,000,000,000 毫秒。这相当于从 1970 年 1 月 1 日凌晨 0 时 0 分 0 秒(UTC)起,支持的时间值范围精确为
-100,000,000 天到 100,000,000 天。
1970 年 1 月 1 日凌晨 0 时 0 分 0 秒(UTC)这一确切时刻用时间值 +0 𝔽 表示。
注
在公历日期中,闰年是精确地指能被 4 整除且要么能被 400 整除,要么不能被 100 整除的年份。
公历日期的 400 年周期包含 97 个闰年。这产生了平均每年 365.2425 天,相当于 31,556,952,000 毫秒。因此,数字可以用毫秒精度精确表示的最大范围约为相对于 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 (一个 有限的
时间值 )
并返回一个 整数 。它返回 t 所在的天数编号。调用时执行以下步骤:
1. 返回 𝔽 (floor (ℝ (t /
msPerDay ))).
21.4.1.4 TimeWithinDay ( t )
抽象操作 TimeWithinDay 接受参数 t (一个 有限的
时间值 )
并返回 整数 ,
该整数在从 +0 𝔽 (包括)到 msPerDay (不包括)的
区间
内。它返回 t 所在天的起始时间之后的毫秒数。调用时执行以下步骤:
1. 返回 𝔽 (ℝ (t )
modulo ℝ (msPerDay )).
21.4.1.5 DaysInYear ( y )
抽象操作 DaysInYear 接受参数 y (一个 整数 ),
并返回 365 𝔽 或 366 𝔽 。它返回年份 y 中的天数。闰年有
366 天;所有其他年份有 365 天。调用时执行以下步骤:
1. 令 ry 为 ℝ (y )。
2. 如果 (ry modulo 400) = 0,则返回
366 𝔽 。
3. 如果 (ry modulo 100) = 0,则返回
365 𝔽 。
4. 如果 (ry modulo 4) = 0,则返回
366 𝔽 。
5. 返回 365 𝔽 。
21.4.1.6 DayFromYear ( y )
抽象操作 DayFromYear 接受参数 y (一个 整数 ),并返回一个 整数 。它返回年份 y
的第一天的天数编号。调用时执行以下步骤:
1. 令 ry 为 ℝ (y )。
2.
注意:在以下步骤中,numYears1 、numYears4 、numYears100 和
numYears400 分别表示从 纪元 到年份 y 开始之间可被 1、4、100 和 400
整除的年数。如果 y 在 纪元 之前,则该数量为负数。
3. 令 numYears1 为 (ry - 1970)。
4. 令 numYears4 为 floor ((ry - 1969) / 4)。
5. 令 numYears100 为 floor ((ry -
1901) / 100)。
6. 令 numYears400 为 floor ((ry -
1601) / 400)。
7. 返回 𝔽 (365 × numYears1 +
numYears4 - numYears100 + numYears400 )。
21.4.1.7 TimeFromYear ( y )
抽象操作 TimeFromYear 接受参数 y (一个 整数 ),并返回一个 时间值 。它返回年份 y
开始的 时间值 。调用时执行以下步骤:
1. 返回 msPerDay × DayFromYear (y )。
21.4.1.8 YearFromTime ( t )
抽象操作 YearFromTime 接受参数 t (一个 有限的
时间值 ),并返回一个 整数 。它返回 t 所在的年份。调用时执行以下步骤:
1. 返回最接近 +∞ 的最大 整数 y ,使得
TimeFromYear (y ) ≤
t 。
21.4.1.9 DayWithinYear ( t )
抽象操作 DayWithinYear 接受参数 t (一个 有限的 时间值 ),并返回一个 整数 ,在 闭区间
+0 𝔽 到 365 𝔽 之间。调用时执行以下步骤:
1. 返回 Day (t ) - DayFromYear (YearFromTime (t ))。
21.4.1.10 InLeapYear ( t )
抽象操作 InLeapYear 接受参数 t (一个 有限的 时间值 ),并返回
+0 𝔽 或 1 𝔽 。如果 t 在闰年中,则返回
1 𝔽 ;否则返回 +0 𝔽 。调用时执行以下步骤:
1. 如果 DaysInYear (YearFromTime (t )) 是
366 𝔽 ,返回 1 𝔽 ;否则返回
+0 𝔽 。
21.4.1.11 MonthFromTime ( t )
抽象操作 MonthFromTime 接受参数 t (一个 有限的 时间值 ),并返回一个 整数 ,在 闭区间
+0 𝔽 到 11 𝔽 之间。它返回一个表示 t
所在月份的数字。月份值 +0 𝔽 表示一月;1 𝔽
表示二月;2 𝔽 表示三月;3 𝔽
表示四月;4 𝔽 表示五月;5 𝔽
表示六月;6 𝔽 表示七月;7 𝔽
表示八月;8 𝔽 表示九月;9 𝔽
表示十月;10 𝔽 表示十一月;11 𝔽 表示十二月。注意,MonthFromTime(+0 𝔽 ) =
+0 𝔽 ,对应于 1970 年 1 月 1 日星期四。调用时执行以下步骤:
1. 令 inLeapYear 为 InLeapYear (t )。
2. 令 dayWithinYear 为 DayWithinYear (t )。
3. 如果 dayWithinYear 小于
31 𝔽 ,返回 +0 𝔽 。
4. 如果 dayWithinYear 小于 59 𝔽
+ inLeapYear ,返回 1 𝔽 。
5. 如果 dayWithinYear 小于 90 𝔽
+ inLeapYear ,返回 2 𝔽 。
6. 如果 dayWithinYear 小于
120 𝔽 + inLeapYear ,返回 3 𝔽 。
7. 如果 dayWithinYear 小于
151 𝔽 + inLeapYear ,返回 4 𝔽 。
8. 如果 dayWithinYear 小于
181 𝔽 + inLeapYear ,返回 5 𝔽 。
9. 如果 dayWithinYear 小于
212 𝔽 + inLeapYear ,返回 6 𝔽 。
10. 如果 dayWithinYear 小于
243 𝔽 + inLeapYear ,返回 7 𝔽 。
11. 如果 dayWithinYear 小于
273 𝔽 + inLeapYear ,返回 8 𝔽 。
12. 如果 dayWithinYear 小于
304 𝔽 + inLeapYear ,返回 9 𝔽 。
13. 如果 dayWithinYear 小于
334 𝔽 + inLeapYear ,返回 10 𝔽 。
14. 断言 :dayWithinYear 小于
365 𝔽 + inLeapYear 。
15. 返回 11 𝔽 。
21.4.1.12 DateFromTime ( t )
抽象操作 DateFromTime 接受参数 t (一个 有限的 时间值 ),并返回一个 整数 ,在 闭区间
1 𝔽 到 31 𝔽 之间。它返回 t
所在月份的日期。调用时执行以下步骤:
1. 令 inLeapYear 为 InLeapYear (t )。
2. 令 dayWithinYear 为 DayWithinYear (t )。
3. 令 month 为 MonthFromTime (t )。
4. 如果 month 为 +0 𝔽 ,返回
dayWithinYear + 1 𝔽 。
5. 如果 month 为 1 𝔽 ,返回
dayWithinYear - 30 𝔽 。
6. 如果 month 为 2 𝔽 ,返回
dayWithinYear - 58 𝔽 - inLeapYear 。
7. 如果 month 为 3 𝔽 ,返回
dayWithinYear - 89 𝔽 - inLeapYear 。
8. 如果 month 为 4 𝔽 ,返回
dayWithinYear - 119 𝔽 - inLeapYear 。
9. 如果 month 为 5 𝔽 ,返回
dayWithinYear - 150 𝔽 - inLeapYear 。
10. 如果 month 为 6 𝔽 ,返回
dayWithinYear - 180 𝔽 - inLeapYear 。
11. 如果 month 为 7 𝔽 ,返回
dayWithinYear - 211 𝔽 - inLeapYear 。
12. 如果 month 为 8 𝔽 ,返回
dayWithinYear - 242 𝔽 - inLeapYear 。
13. 如果 month 为 9 𝔽 ,返回
dayWithinYear - 272 𝔽 - inLeapYear 。
14. 如果 month 为 10 𝔽 ,返回
dayWithinYear - 303 𝔽 - inLeapYear 。
15. 断言 :month 为
11 𝔽 。
16. 返回 dayWithinYear -
333 𝔽 - inLeapYear 。
21.4.1.13 WeekDay ( t )
抽象操作 WeekDay 接受参数 t (一个 有限的 时间值 ),并返回一个 整数 ,在 闭区间
+0 𝔽 到 6 𝔽 之间。它返回一个表示 t
所在星期几的数字。星期几的值 +0 𝔽 表示星期天;1 𝔽
表示星期一;2 𝔽 表示星期二;3 𝔽
表示星期三;4 𝔽 表示星期四;5 𝔽
表示星期五;6 𝔽 表示星期六。注意,WeekDay(+0 𝔽 ) =
4 𝔽 ,对应于 1970 年 1 月 1 日星期四。调用时执行以下步骤:
1. 返回 𝔽 (ℝ (Day (t ) +
4 𝔽 ) modulo 7)。
21.4.1.14 HourFromTime ( t )
抽象操作 HourFromTime 接受参数 t (一个 有限的 时间值 ),并返回一个 整数 ,在 闭区间
+0 𝔽 到 23 𝔽 之间。它返回 t
所在的小时。调用时执行以下步骤:
1. 返回 𝔽 (floor (ℝ (t /
msPerHour )) modulo HoursPerDay )。
21.4.1.15 MinFromTime ( t )
抽象操作 MinFromTime 接受参数 t (一个 有限的 时间值 ),并返回一个 整数 ,在 闭区间
+0 𝔽 到 59 𝔽 之间。它返回 t
所在的分钟。调用时执行以下步骤:
1. 返回 𝔽 (floor (ℝ (t /
msPerMinute )) modulo
MinutesPerHour )。
21.4.1.16 SecFromTime ( t )
抽象操作 SecFromTime 接受参数 t (一个 有限的 时间值 ),并返回一个 整数 ,在 闭区间
+0 𝔽 到 59 𝔽 之间。它返回 t
所在分钟的秒数。调用时执行以下步骤:
1. 返回 𝔽 (floor (ℝ (t /
msPerSecond )) modulo
SecondsPerMinute )。
21.4.1.17 msFromTime ( t )
抽象操作 msFromTime 接受参数 t (一个 有限的 时间值 ),并返回一个 整数 ,在 闭区间
+0 𝔽 到 999 𝔽 之间。它返回 t
所在秒的毫秒数。调用时执行以下步骤:
1. 返回 𝔽 (ℝ (t )
modulo ℝ (msPerSecond ))。
21.4.1.18 GetUTCEpochNanoseconds ( year , month ,
day , hour , minute , second , millisecond ,
microsecond , nanosecond )
抽象操作 GetUTCEpochNanoseconds 接受参数 year (一个 整数 )、month (一个 整数 ,在 闭区间 1 到 12 之间)、day (一个
整数 ,在
闭区间 1 到 31 之间)、hour (一个
整数 ,在
闭区间 0 到 23 之间)、minute (一个
整数 ,在
闭区间 0 到 59 之间)、second (一个
整数 ,在
闭区间 0 到 59
之间)、millisecond (一个 整数 ,在 闭区间 0 到 999
之间)、microsecond (一个 整数 ,在 闭区间 0 到 999 之间)和
nanosecond (一个 整数 ,在 闭区间 0 到 999
之间),返回一个 BigInt。返回值表示自 纪元 以来的纳秒数,对应给定的 ISO 8601 日历日期和 UTC 时间。调用时执行以下步骤:
1. 让 date 等于 MakeDay (𝔽 (year ),
𝔽 (month - 1), 𝔽 (day ))。
2. 让 time 等于 MakeTime (𝔽 (hour ),
𝔽 (minute ), 𝔽 (second ), 𝔽 (millisecond ))。
3. 让 ms 等于 MakeDate (date ,
time )。
4. 断言 :ms 是一个 整数 。
5. 返回 ℤ (ℝ (ms ) × 10** 6 + microsecond × 10** 3 + nanosecond )。
21.4.1.19 Time Zone Identifiers
ECMAScript 中的时区由时区标识符 表示,这些标识符是完全由闭区间 从0x0000到0x007F中的代码单元组成的字符串。
ECMAScript 实现支持的时区可以是可用命名时区 ,由时区标识符记录 的[[Identifier]] 字段表示,这些记录由AvailableNamedTimeZoneIdentifiers 返回,或者是偏移时区 ,由IsTimeZoneOffsetString 返回true 的字符串表示。
一个主要时区标识符 是某个可用命名时区的首选标识符。
一个非主要时区标识符 是某个可用命名时区的非主要标识符。
一个可用命名时区标识符 可以是主要时区标识符或非主要时区标识符。
每个可用命名时区标识符与一个可用命名时区完全对应。
每个可用命名时区完全对应一个主要时区标识符和零个或多个非主要时区标识符。
ECMAScript 实现必须支持标识符为"UTC" 的可用命名时区,它必须是 UTC 时区的主要时区标识符。
此外,实现可以支持任意数量的其他可用命名时区。
遵循 ECMA-402 国际化 API 规范中描述的时区要求的实现称为时区感知 。
时区感知的实现必须支持与 IANA 时区数据库的区域和链接名称对应的可用命名时区,并且仅支持这些名称。
在时区感知的实现中,主要时区标识符是 IANA 时区数据库中的区域名称,非主要时区标识符是链接名称,除非被AvailableNamedTimeZoneIdentifiers 明确覆盖,如
ECMA-402 规范中所述。
即使不支持整个 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 中的挂钟时间。
当输入表示由于负时区转换(例如,当夏令时结束或时区规则更改导致时区偏移减少)而发生多次的本地时间时,返回的列表将有多个元素,并按数值升序排序。
当输入表示由于正时区转换(例如,当夏令时开始或时区规则更改导致时区偏移增加)而跳过的本地时间时,返回的列表将为空。
否则,返回的列表将只有一个元素。
在不包含任何时区本地政治规则的 ECMAScript 实现中,GetNamedTimeZoneEpochNanoseconds 的默认实现在调用时执行以下步骤:
1. 断言 :timeZoneIdentifier 是"UTC" 。
2. 让epochNanoseconds 成为GetUTCEpochNanoseconds (year ,
month , day , hour , minute , second ,
millisecond , microsecond , nanosecond )。
3. 返回« epochNanoseconds »。
注
对于时区感知 实现(并推荐给所有其他实现),使用
IANA 时区数据库的信息https://www.iana.org/time-zones/ 。
2017年11月5日凌晨1:30在 America/New_York 被重复两次,因此
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日凌晨2:30在 America/New_York 不存在,因此
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 标识的命名时区相对于纪元 的UTC偏移量,单位为纳秒。
在不包含任何时区本地政治规则的 ECMAScript 实现中,GetNamedTimeZoneOffsetNanoseconds 的默认实现在调用时执行以下步骤:
1. 断言 :timeZoneIdentifier 是"UTC" 。
2. 返回 0。
注
21.4.1.22 Time Zone Identifier Record
一个时区标识符记录 是一个记录 ,用于描述一个可用命名时区标识符 及其对应的主要时区标识符 。
时区标识符记录有表61 中列出的字段。
表61: 时区标识符记录 字段
字段名
值
含义
[[Identifier]]
一个字符串
一个可用命名时区标识符 ,由实现支持。
[[PrimaryIdentifier]]
一个字符串
[[Identifier]] 解析到的主要时区标识符 。
注
如果[[Identifier]] 是一个主要时区标识符 ,则[[Identifier]] 等于[[PrimaryIdentifier]] 。
21.4.1.23 AvailableNamedTimeZoneIdentifiers ( )
抽象操作 AvailableNamedTimeZoneIdentifiers 不接受任何参数,返回一个列表 ,其中包含时区标识符记录 。其结果描述了此实现中所有可用命名时区标识符 ,以及每个可用命名时区标识符 对应的主要时区标识符 。列表 按每个时区标识符记录 的[[Identifier]] 字段排序。
支持时区的 实现,包括所有实现了ECMA-402国际化API的实现,必须按照ECMA-402规范实现AvailableNamedTimeZoneIdentifiers抽象操作。对于不是支持时区的 实现,当调用AvailableNamedTimeZoneIdentifiers时执行以下步骤:
1. 如果实现中不包含任何时区的本地政治规则,则
a. 返回«时区标识符记录 { [[Identifier]] : "UTC" , [[PrimaryIdentifier]] : "UTC" } »。
2. 让identifiers 成为唯一可用命名时区标识符 的列表 。
3. 将identifiers 排序,顺序与使用
%Array.prototype.sort% 和 comparefn 为undefined 对相同值的数组进行排序相同。
4. 让result 成为一个新的空列表 。
5. 对于identifiers 的每个元素identifier ,执行
a. 让primary 成为identifier 。
b. 如果identifier 在此实现中是一个非主要时区标识符 且identifier 不是"UTC" ,则
i. 将primary 设置为与identifier 关联的主要时区标识符 。
ii. 注意:实现可能需要迭代解析identifier 以获得主要时区标识符 。
c. 让record 成为时区标识符记录 { [[Identifier]] : identifier , [[PrimaryIdentifier]] : primary }。
d. 将record 追加到result 。
6. 断言 :result 包含一个时区标识符记录
r ,其中r .[[Identifier]] 是"UTC" 且r .[[PrimaryIdentifier]] 是"UTC" 。
7. 返回result 。
21.4.1.24 SystemTimeZoneIdentifier ( )
实现定义的 抽象操作SystemTimeZoneIdentifier不接受任何参数并返回一个字符串。它返回一个表示宿主环境 当前时区的字符串,该字符串要么是一个表示UTC偏移的字符串,对于该字符串IsTimeZoneOffsetString 返回true ,要么是一个主要时区标识符 。调用时执行以下步骤:
1. 如果实现只支持UTC时区,则返回"UTC" 。
2. 让systemTimeZoneString 成为表示宿主环境 当前时区的字符串,该字符串可以是主要时区标识符 或偏移时区 标识符。
3. 返回systemTimeZoneString 。
注
为了确保实现通常在Date对象的方法中提供的功能级别,建议SystemTimeZoneIdentifier返回一个对应于宿主环境 的时区设置的IANA时区名称(如果存在这样的名称)。GetNamedTimeZoneEpochNanoseconds 和GetNamedTimeZoneOffsetNanoseconds 必须反映该时区的标准时间和夏令时的本地政治规则(如果存在这些规则)。
例如,如果宿主环境 是用户在系统上选择了美国东部时间作为其时区的浏览器,SystemTimeZoneIdentifier返回"America/New_York" 。
21.4.1.25 LocalTime ( t )
抽象操作LocalTime接受参数t (一个有限 的时间值 ),并返回一个整数 。它将t 从UTC转换为本地时间。应使用t 时当地标准时间和夏令时的政治规则确定结果。调用时执行以下步骤:
1. 让systemTimeZoneIdentifier 成为SystemTimeZoneIdentifier ()的返回值。
2. 如果IsTimeZoneOffsetString (systemTimeZoneIdentifier )为true ,则:
a. 让offsetNs 成为ParseTimeZoneOffsetString (systemTimeZoneIdentifier )的返回值。
3. 否则:
a. 让offsetNs 成为GetNamedTimeZoneOffsetNanoseconds (systemTimeZoneIdentifier ,
ℤ (ℝ (t ) ×
10** 6 ))的返回值。
4. 让offsetMs 成为truncate (offsetNs /
10** 6 )的返回值。
5. 返回t + 𝔽 (offsetMs )。
注 1
注 2
注 3
在负时区转换时(例如夏令时结束或时区调整减少),两个不同的输入时间值 t UTC 转换为相同的本地时间tlocal 。
LocalTime(UTC (t local )) 不一定总是等于t local 。相应地,UTC (LocalTime(t UTC )) 不一定总是等于t UTC 。
21.4.1.26 UTC ( t )
抽象操作UTC接受参数t (一个数字)并返回一个时间值 。它将t 从本地时间转换为UTC时间值 。应使用t 时当地标准时间和夏令时的政治规则确定结果。调用时执行以下步骤:
1. 如果t 不是有限 的,返回NaN 。
2. 让systemTimeZoneIdentifier 成为SystemTimeZoneIdentifier ()的返回值。
3. 如果IsTimeZoneOffsetString (systemTimeZoneIdentifier )为true ,则:
a. 让offsetNs 成为ParseTimeZoneOffsetString (systemTimeZoneIdentifier )的返回值。
4. 否则:
a. 让possibleInstants 成为GetNamedTimeZoneEpochNanoseconds (systemTimeZoneIdentifier ,
ℝ (YearFromTime (t )),
ℝ (MonthFromTime (t ))
+ 1, ℝ (DateFromTime (t )),
ℝ (HourFromTime (t )),
ℝ (MinFromTime (t )),
ℝ (SecFromTime (t )),
ℝ (msFromTime (t )), 0,
0)的返回值。
b.
注意:以下步骤确保当t 表示负时区转换(例如夏令时结束或由于时区规则更改减少时区偏移)时多次重复的本地时间或正时区转换(例如夏令时开始或由于时区规则更改增加时区偏移)时跳过的本地时间时,t 使用转换前的时区偏移进行解释。
c. 如果possibleInstants 不为空,则:
i.
让disambiguatedInstant 成为possibleInstants [0]。
d. 否则:
i. 注意:t 表示正时区转换时跳过的本地时间(例如由于夏令时开始或时区规则更改增加UTC偏移)。
ii. 让possibleInstantsBefore 成为GetNamedTimeZoneEpochNanoseconds (systemTimeZoneIdentifier ,
ℝ (YearFromTime (tBefore )),
ℝ (MonthFromTime (tBefore ))
+ 1, ℝ (DateFromTime (tBefore )),
ℝ (HourFromTime (tBefore )),
ℝ (MinFromTime (tBefore )),
ℝ (SecFromTime (tBefore )),
ℝ (msFromTime (tBefore )),
0, 0),其中tBefore 是t 之前的最大整数 ,并且possibleInstantsBefore 不为空(即tBefore 表示转换前的最后一个本地时间)。
iii.
让disambiguatedInstant 成为possibleInstantsBefore 的最后一个元素。
e. 让offsetNs 成为GetNamedTimeZoneOffsetNanoseconds (systemTimeZoneIdentifier ,
disambiguatedInstant )的返回值。
5. 让offsetMs 成为truncate (offsetNs /
10** 6 )的返回值。
6. 返回t - 𝔽 (offsetMs )。
输入t 名义上是一个时间值 ,但可以是任何数字值。算法不得将t 限制在时间值 范围内,以便支持对应于时间值 范围边界的输入,而不考虑本地UTC偏移。例如,最大时间值 是8.64 × 10** 15 ,对应于"+275760-09-13T00:00:00Z" 。在本地时区偏移在该时刻比UTC提前1小时的环境中,它由更大的输入8.64
× 10** 15 + 3.6 × 10** 6 表示,对应于"+275760-09-13T01:00:00+01:00" 。
如果实现中没有本地时间t 的政治规则,结果是t ,因为SystemTimeZoneIdentifier 返回"UTC" 且GetNamedTimeZoneOffsetNanoseconds 返回0。
注 1
对于支持时区的 实现(并且建议所有其他实现)来说,必须使用IANA时区数据库的信息https://www.iana.org/time-zones/ 。
2017年11月5日凌晨1:30在America/New_York被重复两次(倒退),但它必须被解释为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日凌晨2:30在America/New_York不存在,但它必须被解释为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 (一个数字)、min (一个数字)、sec (一个数字)和
ms (一个数字),并返回一个数字。它计算毫秒数。当被调用时执行以下步骤:
1. 如果 hour 不是 有限的 ,min 不是 有限的 ,sec 不是 有限的 ,或者
ms 不是 有限的 ,返回 NaN 。
2. 让 h 等于 𝔽 (! ToIntegerOrInfinity (hour ))。
3. 让 m 等于 𝔽 (! ToIntegerOrInfinity (min ))。
4. 让 s 等于 𝔽 (! ToIntegerOrInfinity (sec ))。
5. 让 milli 等于 𝔽 (! ToIntegerOrInfinity (ms ))。
6. 返回 ((h × msPerHour + m × msPerMinute ) + s ×
msPerSecond ) + milli 。
注
MakeTime 中的算术运算是浮点运算,它不是结合律的,因此必须按正确的顺序执行操作。
21.4.1.28 MakeDay ( year , month , date )
抽象操作 MakeDay 接受参数 year (一个数字)、month (一个数字)和
date (一个数字),并返回一个数字。它计算天数。当被调用时执行以下步骤:
1. 如果 year 不是 有限的 ,month 不是 有限的 ,或
date 不是 有限的 ,返回 NaN 。
2. 让 y 等于 𝔽 (! ToIntegerOrInfinity (year ))。
3. 让 m 等于 𝔽 (! ToIntegerOrInfinity (month ))。
4. 让 dt 等于 𝔽 (! ToIntegerOrInfinity (date ))。
5. 让 ym 等于 y 加上 𝔽 (floor (ℝ (m ) / 12))。
6. 如果 ym 不是 有限的 ,返回 NaN 。
7. 让 mn 等于 𝔽 (ℝ (m )
modulo 12)。
8. 找到一个 有限的 时间值 t ,使得
YearFromTime (t ) 是
ym ,MonthFromTime (t ) 是
mn ,并且 DateFromTime (t ) 是
1 𝔽 ;但如果这不可能(因为某些参数超出范围),返回 NaN 。
9. 返回 Day (t ) 加上 dt 减去
1 𝔽 。
21.4.1.29 MakeDate ( day , time )
抽象操作 MakeDate 接受参数 day (一个数字)和 time (一个数字),并返回一个数字。它计算毫秒数。当被调用时执行以下步骤:
1. 如果 day 不是 有限的 或 time 不是 有限的 ,返回
NaN 。
2. 让 tv 等于 day 乘以 msPerDay 加上
time 。
3. 如果 tv 不是 有限的 ,返回 NaN 。
4. 返回 tv 。
21.4.1.30 MakeFullYear ( year )
抽象操作 MakeFullYear 接受参数 year (一个数字)并返回一个
整数
或 NaN 。它返回与 year 的整数部分相关的完整年份,将 0 到 99 之间的任何值解释为从 1900 年开始的年份数。
为了与历法对齐,“完整年份”被定义为自 0 年(公元前 1 年)开始的完整年份的有符号计数。当被调用时执行以下步骤:
1. 如果 year 是 NaN ,返回
NaN 。
2. 令 truncated 为 ! ToIntegerOrInfinity (year )。
3. 如果 truncated 在 0 到 99 的
区间内 ,
返回 1900 𝔽 + 𝔽 (truncated )。
4. 返回 𝔽 (truncated )。
21.4.1.31 TimeClip ( time )
抽象操作 TimeClip 接受参数 time (一个数字)并返回一个数字。它计算毫秒数。当被调用时执行以下步骤:
1. 如果 time 不是 有限的 ,返回 NaN 。
2. 如果 abs (ℝ (time )) > 8.64 × 10** 15 ,返回 NaN 。
3. 返回 𝔽 (! ToIntegerOrInfinity (time ))。
21.4.1.32 日期时间字符串格式
ECMAScript 定义了一种基于 ISO 8601 日历日期扩展格式的日期时间字符串交换格式。格式如下:YYYY-MM-DDTHH:mm:ss.sssZ
其中各元素如下:
YYYY
是公历纪年的年份,以四位十进制数字表示,范围从 0000 到 9999,或者是以 扩展年份 的形式,由
"+" 或 "-" 后跟六位十进制数字表示。
-
"-" (连字符)在字符串中出现两次。
MM
是年份中的月份,以两位十进制数字表示,从 01(1月)到 12(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偏移字符串交换格式。
该格式由以下语法描述。
该语法中使用的Unicode代码点列在表62 中。
表62:时区偏移字符串代码点
代码点
Unicode名称
缩写
U+2212
负号
<MINUS>
语法
UTCOffset
:::
TemporalSign
Hour
TemporalSign
Hour
HourSubcomponents [+Extended]
TemporalSign
Hour
HourSubcomponents [~Extended]
TemporalSign
:::
ASCIISign
<MINUS>
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 (一个字符串),并返回一个布尔值。返回值指示 offsetString
是否符合 UTCOffset
给出的语法。调用时执行以下步骤:
1. 令 parseResult 为 ParseText (StringToCodePoints (offsetString ),
UTCOffset )。
2. 如果 parseResult 是一个 列表 的错误,返回
false 。
3. 返回 true 。
21.4.1.33.2 ParseTimeZoneOffsetString ( offsetString )
抽象操作 ParseTimeZoneOffsetString 接受参数 offsetString (一个字符串),并返回一个 整数 。返回值是与字符串
offsetString 对应的 UTC 偏移量,单位为纳秒。调用时执行以下步骤:
1. 令 parseResult 为 ParseText (StringToCodePoints (offsetString ),
UTCOffset )。
2. 断言 :parseResult 不是 错误列表 。
3. 断言 :parseResult 包含一个 TemporalSign
解析节点 。
4. 令 parsedSign 为包含在 parseResult 中的 TemporalSign
解析节点 匹配的 源文本 。
5. 如果 parsedSign 是单个代码点 U+002D(连字符-减号)或 U+2212(减号),则
a. 令 sign 为 -1。
6. 否则,
a. 令 sign 为 1。
7. 注意:下面应用 StringToNumber
不会丢失精度,因为每个解析的值都保证是足够短的十进制数字字符串。
8. 断言 :parseResult 包含一个 Hour 解析节点 。
9. 令 parsedHours 为包含在 parseResult 中的 Hour 解析节点 匹配的 源文本 。
10. 令 hours 为 ℝ (StringToNumber (CodePointsToString (parsedHours )))。
11. 如果 parseResult 不包含一个 MinuteSecond 解析节点 ,则
a. 令 minutes 为 0。
12. 否则,
a. 令 parsedMinutes 为包含在 parseResult
中的第一个 MinuteSecond 解析节点 匹配的 源文本 。
b. 令 minutes 为 ℝ (StringToNumber (CodePointsToString (parsedMinutes )))。
13. 如果 parseResult 不包含两个 MinuteSecond 解析节点 ,则
a. 令 seconds 为 0。
14. 否则,
a. 令 parsedSeconds 为包含在 parseResult
中的第二个 MinuteSecond 解析节点 匹配的 源文本 。
b. 令 seconds 为 ℝ (StringToNumber (CodePointsToString (parsedSeconds )))。
15. 如果 parseResult 不包含 TemporalDecimalFraction
解析节点 ,则
a. 令 nanoseconds 为 0。
16. 否则,
a. 令 parsedFraction 为包含在 parseResult 中的
TemporalDecimalFraction
解析节点 匹配的 源文本 。
b. 令 fraction 为 字符串连接 CodePointsToString (parsedFraction )
和 "000000000" 。
c. 令 nanosecondsString 为 fraction
的子字符串,从第一个字符到第十个字符。
d. 令 nanoseconds 为 ℝ (StringToNumber (nanosecondsString ))。
17. 返回 sign × (((hours × 60 +
minutes ) × 60 + seconds ) × 10** 9 +
nanoseconds )。
21.4.2 Date 构造函数
Date 构造函数 constructor :
是 %Date% 。
是 全局对象 的 "Date"
属性的初始值。
在作为 构造函数 调用时创建并初始化一个新的 Date。
在作为函数而不是 构造函数 调用时返回表示当前时间(UTC)的字符串。
是一个行为根据其参数的数量和类型而不同的函数。
可以用作类定义的 extends
子句的值。继承 Date 指定行为的子类 构造函数 必须包含对 Date 构造函数
的 super
调用,以创建并初始化带有 [[DateValue]] 内部槽的子类实例。
21.4.2.1 Date ( ...values )
调用此函数时执行以下步骤:
1. 如果 NewTarget 是 undefined ,则
a. 令 now 为标识当前时间的 时间值 (UTC)。
b. 返回 ToDateString (now )。
2. 令 numberOfArgs 为 values 中元素的数量。
3. 如果 numberOfArgs = 0,则
a. 令 dv 为标识当前时间的 时间值 (UTC)。
4. 否则,如果 numberOfArgs = 1,则
a. 令 value 为 values [0]。
b. 如果 value 是对象 并且
value 有一个 [[DateValue]] 内部槽,则
i. 令 tv 为 value .[[DateValue]] 。
c. 否则,
i. 令 v 为 ? ToPrimitive (value )。
ii. 如果 v 是字符串 ,则
1. 断言 :下一步永远不会返回 中断完成 ,因为
v 是字符串 。
2. 令 tv 为按完全相同的方式解析 v 作为日期的结果,如
parse
方法 (21.4.3.2 )。
iii. 否则,
1. 令 tv 为 ? ToNumber (v )。
d. 令 dv 为 TimeClip (tv )。
5. 否则,
a. 断言 :numberOfArgs ≥ 2。
b. 令 y 为 ? ToNumber (values [0])。
c. 令 m 为 ? ToNumber (values [1])。
d. 如果 numberOfArgs > 2,令 dt 为
? ToNumber (values [2]);否则令 dt 为
1 𝔽 。
e. 如果 numberOfArgs > 3,令 h 为
? ToNumber (values [3]);否则令 h 为
+0 𝔽 。
f. 如果 numberOfArgs > 4,令 min 为
? ToNumber (values [4]);否则令 min 为
+0 𝔽 。
g. 如果 numberOfArgs > 5,令 s 为
? ToNumber (values [5]);否则令 s 为
+0 𝔽 。
h. 如果 numberOfArgs > 6,令 milli 为
? ToNumber (values [6]);否则令 milli 为
+0 𝔽 。
i. 令 yr 为 MakeFullYear (y )。
j. 令 finalDate 为 MakeDate (MakeDay (yr ,
m , dt ), MakeTime (h ,
min , s , milli ))。
k. 令 dv 为 TimeClip (UTC (finalDate ))。
6. 令 O 为 ? OrdinaryCreateFromConstructor (NewTarget,
"%Date.prototype%" , « [[DateValue]] »)。
7. 设置 O .[[DateValue]] 为
dv 。
8. 返回 O 。
21.4.3 Date 构造函数的属性
Date 构造函数 具有以下属性:
21.4.3.1 Date.now ( )
此函数返回标识调用发生时 UTC 日期和时间的 时间值 。
21.4.3.2 Date.parse ( string )
该函数对其参数应用 ToString 操作符。如果 ToString 结果为 异常完成 ,则立即返回该
完成记录 。否则,该函数将结果字符串解释为日期和时间;它返回一个数字,该数字是对应于该日期和时间的
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
prototype object 。
此属性具有以下属性:{ [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
false }。
21.4.3.4 Date.UTC ( year [ , month [ , date
[ , hours [ , minutes [ , seconds [ , ms ] ] ] ] ] ] )
调用此函数时执行以下步骤:
1. 令 y 为 ? ToNumber (year )。
2. 如果 month 存在,令 m 为 ? ToNumber (month );否则令 m 为
+0 𝔽 。
3. 如果 date 存在,令 dt 为 ? ToNumber (date );否则令 dt 为
1 𝔽 。
4. 如果 hours 存在,令 h 为 ? ToNumber (hours );否则令 h 为
+0 𝔽 。
5. 如果 minutes 存在,令 min 为 ? ToNumber (minutes );否则令 min 为
+0 𝔽 。
6. 如果 seconds 存在,令 s 为 ? ToNumber (seconds );否则令 s 为
+0 𝔽 。
7. 如果 ms 存在,令 milli 为 ? ToNumber (ms );否则令 milli 为
+0 𝔽 。
8. 令 yr 为 MakeFullYear (y )。
9. 返回 TimeClip (MakeDate (MakeDay (yr , m ,
dt ), MakeTime (h ,
min , s , milli )))。
此函数的 "length" 属性值为 7 𝔽 。
注
此函数与 Date constructor 的不同之处在于它返回一个 Number 类型的
time value ,而不是创建一个
Date 对象,并且它将参数解释为 UTC 而不是本地时间。
21.4.4 Date 原型对象的属性
Date 原型对象 :
是 %Date.prototype% 。
本身是一个 普通对象 。
不是 Date 实例,并且没有 [[DateValue]] 内部槽。
具有 [[Prototype]] 内部槽,其值是 %Object.prototype% 。
除非明确定义为其他情况,下面定义的 Date 原型对象的方法不是泛型方法,传递给它们的 this 值必须是具有 [[DateValue]] 内部槽的对象,并且该槽已被初始化为 时间值 。
21.4.4.1 Date.prototype.constructor
初始值 Date.prototype.constructor
是 %Date% 。
21.4.4.2 Date.prototype.getDate ( )
调用此方法时执行以下步骤:
1. 令 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 令 t 为 dateObject .[[DateValue]] 。
4. 如果 t 是 NaN ,返回
NaN 。
5. 返回 DateFromTime (LocalTime (t ))。
21.4.4.3 Date.prototype.getDay ( )
调用此方法时执行以下步骤:
1. 令 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 令 t 为 dateObject .[[DateValue]] 。
4. 如果 t 是 NaN ,返回
NaN 。
5. 返回 WeekDay (LocalTime (t ))。
21.4.4.4 Date.prototype.getFullYear ( )
调用此方法时执行以下步骤:
1. 令 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 令 t 为 dateObject .[[DateValue]] 。
4. 如果 t 是 NaN ,返回
NaN 。
5. 返回 YearFromTime (LocalTime (t ))。
21.4.4.5 Date.prototype.getHours ( )
调用此方法时执行以下步骤:
1. 令 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 令 t 为 dateObject .[[DateValue]] 。
4. 如果 t 是 NaN ,返回
NaN 。
5. 返回 HourFromTime (LocalTime (t ))。
21.4.4.6 Date.prototype.getMilliseconds ( )
调用此方法时执行以下步骤:
1. 令 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 令 t 为 dateObject .[[DateValue]] 。
4. 如果 t 是 NaN ,返回
NaN 。
5. 返回 msFromTime (LocalTime (t ))。
21.4.4.7 Date.prototype.getMinutes ( )
调用此方法时执行以下步骤:
1. 令 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 令 t 为 dateObject .[[DateValue]] 。
4. 如果 t 是 NaN ,返回
NaN 。
5. 返回 MinFromTime (LocalTime (t ))。
21.4.4.8 Date.prototype.getMonth ( )
调用此方法时执行以下步骤:
1. 令 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 令 t 为 dateObject .[[DateValue]] 。
4. 如果 t 是 NaN ,返回
NaN 。
5. 返回 MonthFromTime (LocalTime (t ))。
21.4.4.9 Date.prototype.getSeconds ( )
调用此方法时执行以下步骤:
1. 令 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 令 t 为 dateObject .[[DateValue]] 。
4. 如果 t 是 NaN ,返回
NaN 。
5. 返回 SecFromTime (LocalTime (t ))。
21.4.4.10 Date.prototype.getTime ( )
调用此方法时执行以下步骤:
1. 令 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 返回 dateObject .[[DateValue]] 。
21.4.4.11 Date.prototype.getTimezoneOffset ( )
调用此方法时执行以下步骤:
1. 令 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 令 t 为 dateObject .[[DateValue]] 。
4. 如果 t 是 NaN ,返回
NaN 。
5. 返回 (t - LocalTime (t )) / msPerMinute 。
21.4.4.12 Date.prototype.getUTCDate ( )
调用此方法时执行以下步骤:
1. 令 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 令 t 为 dateObject .[[DateValue]] 。
4. 如果 t 是 NaN ,返回
NaN 。
5. 返回 DateFromTime (t )。
21.4.4.13 Date.prototype.getUTCDay ( )
调用此方法时执行以下步骤:
1. 令 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 令 t 为 dateObject .[[DateValue]] 。
4. 如果 t 是 NaN ,返回
NaN 。
5. 返回 WeekDay (t )。
21.4.4.14 Date.prototype.getUTCFullYear ( )
调用此方法时执行以下步骤:
1. 令 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 令 t 为 dateObject .[[DateValue]] 。
4. 如果 t 是 NaN ,返回
NaN 。
5. 返回 YearFromTime (t )。
21.4.4.15 Date.prototype.getUTCHours ( )
调用此方法时执行以下步骤:
1. 令 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 令 t 为 dateObject .[[DateValue]] 。
4. 如果 t 是 NaN ,返回
NaN 。
5. 返回 HourFromTime (t )。
21.4.4.16 Date.prototype.getUTCMilliseconds ( )
调用此方法时执行以下步骤:
1. 令 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 令 t 为 dateObject .[[DateValue]] 。
4. 如果 t 是 NaN ,返回
NaN 。
5. 返回 msFromTime (t )。
21.4.4.17 Date.prototype.getUTCMinutes ( )
调用此方法时执行以下步骤:
1. 令 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 令 t 为 dateObject .[[DateValue]] 。
4. 如果 t 是 NaN ,返回
NaN 。
5. 返回 MinFromTime (t )。
21.4.4.18 Date.prototype.getUTCMonth ( )
调用此方法时执行以下步骤:
1. 令 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 令 t 为 dateObject .[[DateValue]] 。
4. 如果 t 是 NaN ,返回
NaN 。
5. 返回 MonthFromTime (t )。
21.4.4.19 Date.prototype.getUTCSeconds ( )
调用此方法时执行以下步骤:
1. 令 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 令 t 为 dateObject .[[DateValue]] 。
4. 如果 t 是 NaN ,返回
NaN 。
5. 返回 SecFromTime (t )。
21.4.4.20 Date.prototype.setDate ( date )
调用此方法时执行以下步骤:
1. 令 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 令 t 为 dateObject .[[DateValue]] 。
4. 令 dt 为 ? ToNumber (date )。
5. 如果 t 是 NaN ,返回
NaN 。
6. 将 t 设置为 LocalTime (t )。
7. 令 newDate 为 MakeDate (MakeDay (YearFromTime (t ),
MonthFromTime (t ),
dt ), TimeWithinDay (t ))。
8. 令 u 为 TimeClip (UTC (newDate ))。
9. 将 dateObject .[[DateValue]]
设置为 u 。
10. 返回 u 。
21.4.4.21 Date.prototype.setFullYear ( year [ , month
[ , date ] ] )
调用此方法时执行以下步骤:
1. 令 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 令 t 为 dateObject .[[DateValue]] 。
4. 令 y 为 ? ToNumber (year )。
5. 如果 t 是 NaN ,将 t 设置为
+0 𝔽 ;否则,将 t 设置为 LocalTime (t )。
6. 如果 month 未传入,令 m 为 MonthFromTime (t );否则,令
m 为 ? ToNumber (month )。
7. 如果 date 未传入,令 dt 为 DateFromTime (t );否则,令
dt 为 ? ToNumber (date )。
8. 令 newDate 为 MakeDate (MakeDay (y , m ,
dt ), TimeWithinDay (t ))。
9. 令 u 为 TimeClip (UTC (newDate ))。
10. 将 dateObject .[[DateValue]]
设置为 u 。
11. 返回 u 。
This method 的 "length" 属性值为 3 𝔽 。
Note
如果 month 未传入,则此方法表现得如同 month 传入了 getMonth()
的返回值一样。如果
date 未传入,则表现得如同 date 传入了 getDate()
的返回值一样。
21.4.4.22 Date.prototype.setHours ( hour [ , min [ ,
sec [ , ms ] ] ] )
调用此方法时执行以下步骤:
1. 令 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 令 t 为 dateObject .[[DateValue]] 。
4. 令 h 为 ? ToNumber (hour )。
5. 如果 min 被传入,令 m 为 ? ToNumber (min )。
6. 如果 sec 被传入,令 s 为 ? ToNumber (sec )。
7. 如果 ms 被传入,令 milli 为 ? ToNumber (ms )。
8. 如果 t 是 NaN ,返回
NaN 。
9. 将 t 设置为 LocalTime (t )。
10. 如果 min 未被传入,令 m 为 MinFromTime (t )。
11. 如果 sec 未被传入,令 s 为 SecFromTime (t )。
12. 如果 ms 未被传入,令 milli 为 msFromTime (t )。
13. 令 date 为 MakeDate (Day (t ),
MakeTime (h , m ,
s , milli ))。
14. 令 u 为 TimeClip (UTC (date ))。
15. 将 dateObject .[[DateValue]]
设置为 u 。
16. 返回 u 。
This method 的 "length" 属性值为 4 𝔽 。
Note
如果 min 未被传入,此方法表现得如同 min 被传入了 getMinutes()
的返回值一样。如果
sec 未被传入,此方法表现得如同 sec 被传入了 getSeconds()
的返回值一样。如果 ms
未被传入,此方法表现得如同 ms 被传入了 getMilliseconds()
的返回值一样。
21.4.4.23 Date.prototype.setMilliseconds ( ms )
调用此方法时执行以下步骤:
1. 令 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 令 t 为 dateObject .[[DateValue]] 。
4. 将 ms 设置为 ? ToNumber (ms )。
5. 如果 t 是 NaN ,返回
NaN 。
6. 将 t 设置为 LocalTime (t )。
7. 令 time 为 MakeTime (HourFromTime (t ),
MinFromTime (t ),
SecFromTime (t ),
ms )。
8. 令 u 为 TimeClip (UTC (MakeDate (Day (t ),
time )))。
9. 将 dateObject .[[DateValue]]
设置为 u 。
10. 返回 u 。
21.4.4.24 Date.prototype.setMinutes ( min [ , sec [ ,
ms ] ] )
调用此方法时执行以下步骤:
1. 令 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 令 t 为 dateObject .[[DateValue]] 。
4. 令 m 为 ? ToNumber (min )。
5. 如果 sec 被传入,令 s 为 ? ToNumber (sec )。
6. 如果 ms 被传入,令 milli 为 ? ToNumber (ms )。
7. 如果 t 是 NaN ,返回
NaN 。
8. 将 t 设置为 LocalTime (t )。
9. 如果 sec 未被传入,令 s 为 SecFromTime (t )。
10. 如果 ms 未被传入,令 milli 为 msFromTime (t )。
11. 令 date 为 MakeDate (Day (t ),
MakeTime (HourFromTime (t ),
m , s , milli ))。
12. 令 u 为 TimeClip (UTC (date ))。
13. 将 dateObject .[[DateValue]]
设置为 u 。
14. 返回 u 。
This method 的 "length" 属性值为 3 𝔽 。
Note
如果 sec 未被传入,此方法表现得如同 sec 被传入了 getSeconds()
的返回值一样。如果 ms
未被传入,此方法表现得如同 ms 被传入了 getMilliseconds()
的返回值一样。
21.4.4.25 Date.prototype.setMonth ( month [ , date ] )
调用此方法时执行以下步骤:
1. 让 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] ).
3. 让 t 为 dateObject .[[DateValue]] 。
4. 让 m 为 ? ToNumber (month ).
5. 如果存在 date ,则让 dt 为 ? ToNumber (date ).
6. 如果 t 为 NaN ,返回
NaN 。
7. 将 t 设置为 LocalTime (t )。
8. 如果 date 不存在,则让 dt 为 DateFromTime (t )。
9. 让 newDate 为 MakeDate (MakeDay (YearFromTime (t ),
m , dt ), TimeWithinDay (t ))。
10. 让 u 为 TimeClip (UTC (newDate ))。
11. 将 dateObject .[[DateValue]]
设置为 u 。
12. 返回 u 。
此方法的 "length" 属性为 2 𝔽 。
注
如果 date 不存在,此方法的行为就像 date 存在且其值为 getDate()
。
21.4.4.26 Date.prototype.setSeconds ( sec [ , ms ] )
调用此方法时执行以下步骤:
1. 让 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] ).
3. 让 t 为 dateObject .[[DateValue]] 。
4. 让 s 为 ? ToNumber (sec ).
5. 如果存在 ms ,则让 milli 为 ? ToNumber (ms ).
6. 如果 t 为 NaN ,返回
NaN 。
7. 将 t 设置为 LocalTime (t )。
8. 如果 ms 不存在,则让 milli 为 msFromTime (t )。
9. 让 date 为 MakeDate (Day (t ),
MakeTime (HourFromTime (t ),
MinFromTime (t ),
s , milli )).
10. 让 u 为 TimeClip (UTC (date ))。
11. 将 dateObject .[[DateValue]]
设置为 u 。
12. 返回 u 。
此方法的 "length" 属性为 2 𝔽 。
注
如果 ms 不存在,此方法的行为就像 ms 存在且其值为 getMilliseconds()
。
21.4.4.27 Date.prototype.setTime ( time )
调用此方法时执行以下步骤:
1. 让 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] ).
3. 让 t 为 ? ToNumber (time ).
4. 让 v 为 TimeClip (t ).
5. 将 dateObject .[[DateValue]]
设置为 v 。
6. 返回 v 。
21.4.4.28 Date.prototype.setUTCDate ( date )
调用此方法时执行以下步骤:
1. 让 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] ).
3. 让 t 为 dateObject .[[DateValue]] 。
4. 让 dt 为 ? ToNumber (date ).
5. 如果 t 是 NaN ,返回
NaN 。
6. 让 newDate 为 MakeDate (MakeDay (YearFromTime (t ),
MonthFromTime (t ),
dt ), TimeWithinDay (t )).
7. 让 v 为 TimeClip (newDate )。
8. 将 dateObject .[[DateValue]]
设置为 v 。
9. 返回 v 。
21.4.4.29 Date.prototype.setUTCFullYear ( year [ ,
month [ , date ] ] )
调用此方法时执行以下步骤:
1. 让 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] ).
3. 让 t 为 dateObject .[[DateValue]] 。
4. 如果 t 是 NaN ,将 t 设置为
+0 𝔽 。
5. 让 y 为 ? ToNumber (year ).
6. 如果没有提供 month ,则让 m 为 MonthFromTime (t );否则,让
m 为 ? ToNumber (month ).
7. 如果没有提供 date ,则让 dt 为 DateFromTime (t );否则,让
dt 为 ? ToNumber (date ).
8. 让 newDate 为 MakeDate (MakeDay (y , m ,
dt ), TimeWithinDay (t )).
9. 让 v 为 TimeClip (newDate ).
10. 将 dateObject .[[DateValue]]
设置为 v 。
11. 返回 v 。
This method's "length" property is 3 𝔽 .
注
如果没有提供 month ,此方法的行为如同提供了值 getUTCMonth()
。如果没有提供 date ,其行为如同提供了值
getUTCDate()
。
21.4.4.30 Date.prototype.setUTCHours ( hour [ , min [
, sec [ , ms ] ] ] )
调用此方法时执行以下步骤:
1. 让 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] ).
3. 让 t 为 dateObject .[[DateValue]] 。
4. 让 h 为 ? ToNumber (hour ).
5. 如果提供了 min ,则让 m 为 ? ToNumber (min )。
6. 如果提供了 sec ,则让 s 为 ? ToNumber (sec )。
7. 如果提供了 ms ,则让 milli 为 ? ToNumber (ms )。
8. 如果 t 是 NaN ,返回
NaN 。
9. 如果没有提供 min ,则让 m 为 MinFromTime (t )。
10. 如果没有提供 sec ,则让 s 为 SecFromTime (t )。
11. 如果没有提供 ms ,则让 milli 为 msFromTime (t )。
12. 让 date 为 MakeDate (Day (t ),
MakeTime (h , m ,
s , milli )).
13. 让 v 为 TimeClip (date )。
14. 将 dateObject .[[DateValue]]
设置为 v 。
15. 返回 v 。
This method's "length" property is 4 𝔽 .
注
如果没有提供 min ,此方法的行为如同提供了值 getUTCMinutes()
。如果没有提供 sec ,其行为如同提供了值
getUTCSeconds()
。如果没有提供 ms ,其行为如同提供了值 getUTCMilliseconds()
。
21.4.4.31 Date.prototype.setUTCMilliseconds ( ms )
调用此方法时执行以下步骤:
1. 让 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] ).
3. 让 t 为 dateObject .[[DateValue]] 。
4. 将 ms 设置为 ? ToNumber (ms )。
5. 如果 t 是 NaN ,返回
NaN 。
6. 让 time 为 MakeTime (HourFromTime (t ),
MinFromTime (t ),
SecFromTime (t ),
ms ).
7. 让 v 为 TimeClip (MakeDate (Day (t ), time )).
8. 将 dateObject .[[DateValue]]
设置为 v 。
9. 返回 v 。
21.4.4.32 Date.prototype.setUTCMinutes ( min [ , sec [
, ms ] ] )
调用此方法时执行以下步骤:
1. 让 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 让 t 为 dateObject .[[DateValue]] 。
4. 让 m 为 ? ToNumber (min )。
5. 如果提供了 sec ,则让 s 为 ? ToNumber (sec )。
6. 如果提供了 ms ,则让 milli 为 ? ToNumber (ms )。
7. 如果 t 是 NaN ,返回
NaN 。
8. 如果没有提供 sec ,则让 s 为 SecFromTime (t )。
9. 如果没有提供 ms ,则让 milli 为 msFromTime (t )。
10. 让 date 为 MakeDate (Day (t ),MakeTime (HourFromTime (t ),m ,s ,milli )).
11. 让 v 为 TimeClip (date )。
12. 将 dateObject .[[DateValue]]
设置为 v 。
13. 返回 v 。
此方法的 "length" 属性是 3 𝔽 。
注
如果没有提供 sec ,此方法的行为如同提供了值 getUTCSeconds()
。如果没有提供 ms ,其行为如同提供了值
getUTCMilliseconds()
。
21.4.4.33 Date.prototype.setUTCMonth ( month [ , date
] )
调用此方法时执行以下步骤:
1. 让 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 让 t 为 dateObject .[[DateValue]] 。
4. 让 m 为 ? ToNumber (month )。
5. 如果提供了 date ,则让 dt 为 ? ToNumber (date )。
6. 如果 t 是 NaN ,返回
NaN 。
7. 如果没有提供 date ,则让 dt 为 DateFromTime (t )。
8. 让 newDate 为 MakeDate (MakeDay (YearFromTime (t ),
m , dt ), TimeWithinDay (t ))。
9. 让 v 为 TimeClip (newDate )。
10. 将 dateObject .[[DateValue]]
设置为 v 。
11. 返回 v 。
此方法的 "length" 属性是 2 𝔽 。
注
如果没有提供 date ,此方法的行为如同提供了值 getUTCDate()
。
21.4.4.34 Date.prototype.setUTCSeconds ( sec [ , ms ]
)
调用此方法时执行以下步骤:
1. 让 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 让 t 为 dateObject .[[DateValue]] 。
4. 让 s 为 ? ToNumber (sec )。
5. 如果提供了 ms ,则让 milli 为 ? ToNumber (ms )。
6. 如果 t 是 NaN ,返回
NaN 。
7. 如果没有提供 ms ,则让 milli 为 msFromTime (t )。
8. 让 date 为 MakeDate (Day (t ),
MakeTime (HourFromTime (t ),
MinFromTime (t ),
s , milli )。
9. 让 v 为 TimeClip (date )。
10. 将 dateObject .[[DateValue]]
设置为 v 。
11. 返回 v 。
此方法的 "length" 属性是 2 𝔽 。
注
如果没有提供 ms ,此方法的行为如同提供了值 getUTCMilliseconds()
。
21.4.4.35 Date.prototype.toDateString ( )
调用此方法时执行以下步骤:
1. 让 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 让 tv 为 dateObject .[[DateValue]] 。
4. 如果 tv 是 NaN ,返回 "Invalid
Date" 。
5. 让 t 为 LocalTime (tv )。
6. 返回 DateString (t )。
21.4.4.36 Date.prototype.toISOString ( )
调用此方法时执行以下步骤:
1. 让 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 让 tv 为 dateObject .[[DateValue]] 。
4. 如果 tv 不是 有限 的,抛出 RangeError 异常。
5. 如果 tv 对应的年份无法在 日期时间字符串格式 中表示,抛出
RangeError 异常。
6. 返回在 UTC 时间尺度上 tv 的字符串表示形式,包括所有格式元素和 UTC 偏移表示
"Z" 。
21.4.4.37 Date.prototype.toJSON ( key )
此方法提供 Date 的字符串表示形式,以供 JSON.stringify
(25.5.2 ) 使用。
调用此方法时执行以下步骤:
1. 让 O 为 ? ToObject (this 值)。
2. 让 tv 为 ? ToPrimitive (O , number )。
3. 如果 tv 是一个数字 并且
tv 不是 有限 的,返回 null 。
4. 返回 ? Invoke (O , "toISOString" )。
注 1
注 2
此方法有意为通用方法;它不要求其 this 值为 Date。因此,它可以转移到其他类型的对象作为方法使用。然而,它确实要求任何这样的对象具有
toISOString
方法。
21.4.4.38 Date.prototype.toLocaleDateString ( [ reserved1 [ ,
reserved2 ] ] )
包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范指定的方法实现此方法。如果 ECMAScript 实现不包含 ECMA-402
API,则使用以下此方法的规范:
此方法返回一个字符串值。字符串的内容是由实现定义的 ,但旨在以方便、人类可读的形式表示当前时区中的日期部分,符合宿主环境 当前区域设置的习惯。
此方法的可选参数的含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得将这些参数位置用于其他任何目的。
21.4.4.39 Date.prototype.toLocaleString ( [ reserved1 [ ,
reserved2 ] ] )
包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范指定的方法实现此方法。如果 ECMAScript 实现不包含 ECMA-402
API,则使用以下此方法的规范:
此方法返回一个字符串值。字符串的内容是由实现定义的 ,但旨在以方便、人类可读的形式表示当前时区中的日期,符合宿主环境 当前区域设置的习惯。
此方法的可选参数的含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得将这些参数位置用于其他任何目的。
21.4.4.40 Date.prototype.toLocaleTimeString ( [ reserved1 [ ,
reserved2 ] ] )
包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范指定的方法实现此方法。如果 ECMAScript 实现不包含 ECMA-402
API,则使用以下此方法的规范:
此方法返回一个字符串值。字符串的内容是由实现定义的 ,但旨在以方便、人类可读的形式表示当前时区中的时间部分,符合宿主环境 当前区域设置的习惯。
此方法的可选参数的含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得将这些参数位置用于其他任何目的。
21.4.4.41 Date.prototype.toString ( )
调用此方法时,它会执行以下步骤:
1. 将 dateObject 设为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 将 tv 设为 dateObject .[[DateValue]] 。
4. 返回 ToDateString (tv )。
注 1
对于任何 Date 对象 d
,如果 d.[[DateValue]]
能被 1000 整除,则
Date.parse(d.toString())
的结果等于 d.valueOf()
。参见 21.4.3.2 。
注 2
此方法不是通用的;如果其 this 值不是 Date,则会抛出 TypeError
异常。因此,不能将其转移到其他类型的对象上作为方法使用。
21.4.4.41.1 TimeString ( tv )
抽象操作 TimeString 接受参数 tv (一个数字,但不能是 NaN ),并返回一个字符串。调用时执行以下步骤:
1. 将 hour 设为 ToZeroPaddedDecimalString (ℝ (HourFromTime (tv )),
2)。
2. 将 minute 设为 ToZeroPaddedDecimalString (ℝ (MinFromTime (tv )), 2)。
3. 将 second 设为 ToZeroPaddedDecimalString (ℝ (SecFromTime (tv )), 2)。
4. 返回 字符串连接
的结果:hour 、":" 、minute 、":" 、second 、代码单元
0x0020 (空格),以及 "GMT" 。
21.4.4.41.2 DateString ( tv )
抽象操作 DateString 接受参数 tv (一个数字,但不能是 NaN ),并返回一个字符串。调用时执行以下步骤:
1. 将 weekday 设为 表 63 中对应 WeekDay (tv ) 的名称。
2. 将 month 设为 表 64 中对应 MonthFromTime (tv )
的名称。
3. 将 day 设为 ToZeroPaddedDecimalString (ℝ (DateFromTime (tv )),
2)。
4. 将 yv 设为 YearFromTime (tv )。
5. 如果 yv 是 +0 𝔽 或
yv > +0 𝔽 ,则将 yearSign 设为空字符串;否则,将
yearSign 设为 "-" 。
6. 将 paddedYear 设为 ToZeroPaddedDecimalString (abs (ℝ (yv )),
4)。
7. 返回 字符串连接
的结果:weekday 、代码单元 0x0020 (空格)、month 、代码单元 0x0020 (空格)、day 、代码单元 0x0020
(空格)、yearSign 和 paddedYear 。
表 63: 一周的日名
编号
名称
+0 𝔽
"Sun"
1 𝔽
"Mon"
2 𝔽
"Tue"
3 𝔽
"Wed"
4 𝔽
"Thu"
5 𝔽
"Fri"
6 𝔽
"Sat"
表 64: 一年中的月份名称
编号
名称
+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 (一个 整数 ),并返回一个字符串。调用时执行以下步骤:
1. 将 systemTimeZoneIdentifier 设为 SystemTimeZoneIdentifier ()。
2. 如果 IsTimeZoneOffsetString (systemTimeZoneIdentifier )
为 true ,则:
a. 将 offsetNs 设为 ParseTimeZoneOffsetString (systemTimeZoneIdentifier )。
3. 否则:
a. 将 offsetNs 设为 GetNamedTimeZoneOffsetNanoseconds (systemTimeZoneIdentifier ,
ℤ (ℝ (tv )
× 106 ))。
4. 将 offset 设为 𝔽 (truncate (offsetNs /
106 ))。
5. 如果 offset 为 +0 𝔽 或
offset > +0 𝔽 ,则:
a. 将 offsetSign 设为 "+" 。
b. 将 absOffset 设为 offset 。
6. 否则:
a. 将 offsetSign 设为 "-" 。
b. 将 absOffset 设为 -offset 。
7. 将 offsetMin 设为 ToZeroPaddedDecimalString (ℝ (MinFromTime (absOffset )),
2)。
8. 将 offsetHour 设为 ToZeroPaddedDecimalString (ℝ (HourFromTime (absOffset )),
2)。
9. 将 tzName 设为一个 实现定义的 字符串,该字符串可以是空字符串或
字符串连接 的结果,其中包含代码单元 0x0020
(空格)、代码单元 0x0028 (左括号)、一个 实现定义的 时区名称和代码单元 0x0029
(右括号)。
10. 返回 字符串连接
的结果:offsetSign 、offsetHour 、offsetMin 和 tzName 。
21.4.4.41.4 ToDateString ( tv )
抽象操作 ToDateString 接受参数 tv (一个 整数 或
NaN ),并返回一个字符串。调用时执行以下步骤:
1. 如果 tv 为 NaN ,则返回 "Invalid
Date" 。
2. 将 t 设为 LocalTime (tv )。
3. 返回 字符串连接 的结果:DateString (t ),代码单元
0x0020 (空格),TimeString (t ),以及
TimeZoneString (tv )。
21.4.4.42 Date.prototype.toTimeString ( )
此方法调用时执行以下步骤:
1. 将 dateObject 设为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 将 tv 设为 dateObject .[[DateValue]] 。
4. 如果 tv 为 NaN ,则返回 "Invalid
Date" 。
5. 将 t 设为 LocalTime (tv )。
6. 返回 字符串连接 的结果:TimeString (t ) 和
TimeZoneString (tv )。
21.4.4.43 Date.prototype.toUTCString ( )
此方法返回一个字符串,表示与 this 值对应的时间瞬间。字符串的格式基于 RFC 7231 中的 "HTTP-date",并扩展支持 ECMAScript
日期所支持的所有时间范围。
调用时执行以下步骤:
1. 将 dateObject 设为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 将 tv 设为 dateObject .[[DateValue]] 。
4. 如果 tv 为 NaN ,则返回 "Invalid
Date" 。
5. 将 weekday 设为 表 63 中与数字 WeekDay (tv ) 对应的名称。
6. 将 month 设为 表 64 中与数字 MonthFromTime (tv )
对应的名称。
7. 将 day 设为 ToZeroPaddedDecimalString (ℝ (DateFromTime (tv )), 2)。
8. 将 yv 设为 YearFromTime (tv )。
9. 如果 yv 为 +0 𝔽 或
yv 大于 +0 𝔽 ,将 yearSign 设为空字符串;否则,将
yearSign 设为 "-" 。
10. 将 paddedYear 设为 ToZeroPaddedDecimalString (abs (ℝ (yv )), 4)。
11. 返回 字符串连接
的结果:weekday ,"," ,空格字符,day ,空格字符,month ,空格字符,yearSign ,paddedYear ,空格字符,以及
TimeString (tv )。
21.4.4.44 Date.prototype.valueOf ( )
此方法调用时执行以下步骤:
1. 将 dateObject 设为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] )。
3. 返回 dateObject .[[DateValue]] 。
21.4.4.45 Date.prototype [ @@toPrimitive ] ( hint )
此方法由 ECMAScript 语言操作符调用,用于将 Date 对象转换为原始值。hint 允许的值为
"default" 、"number" 和 "string" 。在 ECMAScript
内置对象中,Date 对象的唯一特性是将 "default" 视为与 "string" 相同,而所有其他内置 ECMAScript
对象将 "default" 视为与 "number" 相同。
调用时执行以下步骤:
1. 将 O 设为 this 值。
2. 如果 O 不是一个对象 ,则抛出
TypeError 异常。
3. 如果 hint 是 "string" 或
"default" ,则
a. 将 tryFirst 设为 string 。
4. 否则,如果 hint 是 "number" ,则
a. 将 tryFirst 设为 number 。
5. 否则,
a. 抛出 TypeError 异常。
6. 返回 ? OrdinaryToPrimitive (O , tryFirst )。
该属性的特性为 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
true }。
此方法的 "name" 属性值为 "[Symbol.toPrimitive]" 。
21.4.5 Date 实例的属性
Date 实例是 普通对象 ,从 Date 原型对象
继承属性。Date 实例还具有一个 [[DateValue]] 内部槽位。
[[DateValue]] 内部槽位表示此 Date 对象所表示的 时间值 。
22 文本处理
22.1 字符串对象
22.1.1 String 构造函数
String 构造函数 :
是 %String% 。
是 "String" 属性的初始值 全局对象 。
当作为 构造函数 调用时,创建并初始化一个新的 String 对象。
当作为函数而不是 构造函数 调用时,执行类型转换。
可以用作类定义的 extends
子句的值。希望继承指定 String 行为的子类 构造函数 必须包含对 String 构造函数
的 super
调用,以创建并初始化具有 [[StringData]] 内部槽的子类实例。
22.1.1.1 String ( value )
此函数在调用时执行以下步骤:
1. 如果 value 不存在,则
a. 让 s 为空字符串。
2. 否则,
a. 如果 NewTarget 为 undefined 且
value 是
Symbol ,返回 SymbolDescriptiveString (value )。
b. 让 s 为 ? ToString (value )。
3. 如果 NewTarget 为 undefined ,返回 s 。
4. 返回 StringCreate (s ,? GetPrototypeFromConstructor (NewTarget,"%String.prototype%" ))。
22.1.2 String 构造函数的属性
String 构造函数 :
22.1.2.1 String.fromCharCode ( ...codeUnits )
此函数可以用任意数量的参数调用,这些参数组成了剩余参数 codeUnits 。
调用时,它执行以下步骤:
1. 让 result 为空字符串。
2. 对于 codeUnits 的每个元素 next ,执行以下操作:
a. 让 nextCU 为其数值为 ℝ (? ToUint16 (next )) 的代码单元。
b. 将 result 设置为 字符串连接 result 和
nextCU 。
3. 返回 result 。
此函数的 "length" 属性为 1 𝔽 。
22.1.2.2 String.fromCodePoint ( ...codePoints )
此函数可以用任意数量的参数调用,这些参数组成了剩余参数 codePoints 。
调用时,它执行以下步骤:
1. 让 result 为空字符串。
2. 对于 codePoints 的每个元素 next ,执行以下操作:
a. 让 nextCP 为 ? ToNumber (next )。
b. 如果 IsIntegralNumber (nextCP )
为 false ,抛出一个 RangeError 异常。
c. 如果 ℝ (nextCP ) 小于 0 或
ℝ (nextCP ) 大于
0x10FFFF,抛出一个 RangeError 异常。
d. 将 result 设置为 字符串连接 result 和
UTF16EncodeCodePoint (ℝ (nextCP ))。
3. Assert :如果 codePoints 为空,则
result 为空字符串。
4. 返回 result 。
此函数的 "length" 属性为 1 𝔽 。
22.1.2.3 String.prototype
String.prototype
的初始值是 String
原型对象 。
此属性的特性为 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
false }。
22.1.2.4 String.raw ( template , ...substitutions )
此函数可以用可变数量的参数调用。第一个参数是 template ,其余参数组成了 List
substitutions 。
调用时,它执行以下步骤:
1. 让 substitutionCount 为 substitutions 中的元素数量。
2. 让 cooked 为 ? ToObject (template )。
3. 让 literals 为 ? ToObject (? Get (cooked , "raw" ))。
4. 让 literalCount 为 ? LengthOfArrayLike (literals )。
5. 如果 literalCount ≤ 0,则返回空字符串。
6. 让 R 为空字符串。
7. 让 nextIndex 为 0。
8. 重复执行:
a. 让 nextLiteralVal 为 ? Get (literals , ! ToString (𝔽 (nextIndex )))。
b. 让 nextLiteral 为 ? ToString (nextLiteralVal )。
c. 将 R 设置为 字符串连接
R 和 nextLiteral 。
d. 如果 nextIndex + 1 = literalCount ,则返回
R 。
e. 如果 nextIndex 小于 substitutionCount ,则:
i. 让 nextSubVal 为
substitutions [nextIndex ]。
ii. 让 nextSub 为 ? ToString (nextSubVal )。
iii. 将 R 设置为 字符串连接 R 和
nextSub 。
f. 将 nextIndex 增加 1。
注
此函数旨在用作标记模板的标签函数(13.3.11 )。当作为标签函数调用时,第一个参数将是一个格式正确的模板对象,其余参数将包含替代值。
22.1.3 String 原型对象的属性
String 原型对象 :
是 %String.prototype% 。
是一个 String
异域对象 ,并具有为此类对象指定的内部方法。
具有一个 [[StringData]] 内部槽,其值为空字符串。
具有一个 "length" 属性,其初始值为 +0 𝔽 ,其特性为 { [[Writable]] : false , [[Enumerable]] :
false , [[Configurable]] : false }。
具有一个 [[Prototype]] 内部槽,其值为 %Object.prototype% 。
除非另有明确说明,否则下面定义的 String 原型对象的方法不是通用的,传递给它们的 this 值必须是 String 值或具有被初始化为 String 值的 [[StringData]] 内部槽的对象。
22.1.3.1 String.prototype.at ( index )
1. 让 O 为 ? RequireObjectCoercible (this
值)。
2. 让 S 为 ? ToString (O )。
3. 让 len 为 S 的长度。
4. 让 relativeIndex 为 ? ToIntegerOrInfinity (index )。
5. 如果 relativeIndex ≥ 0,则
a. 让 k 为 relativeIndex 。
6. 否则,
a. 让 k 为 len + relativeIndex 。
7. 如果 k
< 0 或 k ≥ len ,返回 undefined 。
8. 返回 substring 从 S 的 k
到 k + 1。
22.1.3.2 String.prototype.charAt ( pos )
注 1
此方法返回一个单一元素的字符串,包含从将此对象转换为字符串后的值的索引 pos 处的代码单元。如果该索引处没有元素,结果是空字符串。结果 是一个
String 值,而不是 String 对象。
如果 pos
是一个 整数 ,那么 x.charAt(pos)
的结果等同于 x.substring(pos, pos + 1)
的结果。
此方法在调用时执行以下步骤:
1. 让 O 为 ? RequireObjectCoercible (this
值)。
2. 让 S 为 ? ToString (O )。
3. 让 position 为 ? ToIntegerOrInfinity (pos )。
4. 让 size 为 S 的长度。
5. 如果 position
< 0 或 position ≥ size ,返回空字符串。
6. 返回 substring 从 S 的
position 到 position + 1。
注 2
此方法故意是通用的;它不要求其 this 值是一个 String 对象。因此,它可以转移到其他类型的对象上作为方法使用。
22.1.3.3 String.prototype.charCodeAt ( pos )
注 1
此方法返回一个数字(一个非负的 整数 ,小于 2** 16 ),它是将此对象转换为字符串后的值在索引 pos
处的代码单元的数值。如果该索引处没有元素,结果是 NaN 。
此方法在调用时执行以下步骤:
1. 让 O 为 ? RequireObjectCoercible (this
值)。
2. 让 S 为 ? ToString (O )。
3. 让 position 为 ? ToIntegerOrInfinity (pos )。
4. 让 size 为 S 的长度。
5. 如果 position
< 0 或 position ≥ size ,返回 NaN 。
6. 返回 Number value for 在字符串
S 中索引 position 处的代码单元的数值。
注 2
此方法故意是通用的;它不要求其 this 值是一个 String 对象。因此,它可以转移到其他类型的对象上作为方法使用。
22.1.3.4 String.prototype.codePointAt ( pos )
注 1
此方法返回一个非负的 整数 ,小于或等于
0x10FFFF 𝔽 ,它是从将此对象转换为字符串后的值中,在索引 pos 处开始的 UTF-16
编码代码点的数值(6.1.4 )。如果该索引处没有元素,结果是
undefined 。如果一个有效的 UTF-16 代理对 不从 pos 开始,结果是索引
pos 处的代码单元。
此方法在调用时执行以下步骤:
1. 让 O 为 ? RequireObjectCoercible (this
值)。
2. 让 S 为 ? ToString (O )。
3. 让 position 为 ? ToIntegerOrInfinity (pos )。
4. 让 size 为 S 的长度。
5. 如果 position
< 0 或 position ≥ size ,返回 undefined 。
6. 让 cp 为 CodePointAt (S ,
position )。
7. 返回 𝔽 (cp .[[CodePoint]] )。
注 2
此方法故意是通用的;它不要求其 this 值是一个 String 对象。因此,它可以转移到其他类型的对象上作为方法使用。
22.1.3.5 String.prototype.concat ( ...args )
注 1
当调用此方法时,它返回一个由 this 值(转换为字符串)的代码单元和每个参数转换为字符串的代码单元组成的字符串值。结果是一个 字符串
值,而不是一个字符串对象。
调用此方法时执行以下步骤:
1. 让 O 为 ? RequireObjectCoercible (this
值)。
2. 让 S 为 ? ToString (O ).
3. 让 R 为 S 。
4. 对于 args 的每个元素 next ,执行
a. 让 nextString 为 ? ToString (next ).
b. 将 R 设置为 字符串连接
的 R 和 nextString 。
5. 返回 R 。
此方法的 "length" 属性为 1 𝔽 。
注 2
此方法具有通用性;它不要求其 this 值是一个字符串对象。因此,它可以转移到其他类型的对象中用作方法。
22.1.3.6 String.prototype.constructor
String.prototype.constructor
的初始值是 %String% 。
22.1.3.7 String.prototype.endsWith ( searchString [ ,
endPosition ] )
调用此方法时执行以下步骤:
1. 让 O 为 ? RequireObjectCoercible (this
值)。
2. 让 S 为 ? ToString (O ).
3. 让 isRegExp 为 ? IsRegExp (searchString ).
4. 如果 isRegExp 为 true ,抛出
TypeError 异常。
5. 让 searchStr 为 ? ToString (searchString ).
6. 让 len 为 S 的长度。
7. 如果 endPosition 为 undefined ,
让 pos 为 len ;否则让 pos 为 ? ToIntegerOrInfinity (endPosition )。
8. 让 end 为将 pos 限制在 0 和 len
之间的结果。
9. 让 searchLength 为 searchStr 的长度。
10. 如果 searchLength 为 0,返回 true 。
11. 让 start 为 end - searchLength 。
12. 如果 start 小于 0,返回 false 。
13. 让 substring 为 substring 从
start
到 end 的 S 。
14. 如果 substring 等于 searchStr ,返回
true 。
15. 返回 false 。
注 1
如果将 searchString 转换为字符串的代码单元序列与该对象(转换为字符串)在 endPosition - length(this)
处的相应代码单元序列相同,则此方法返回 true 。否则返回 false 。
注 2
如果第一个参数是 RegExp,则抛出异常的规定是为了允许将来版本定义扩展,允许这样的参数值。
注 3
此方法具有通用性;它不要求其 this 值是一个字符串对象。因此,它可以转移到其他类型的对象中用作方法。
22.1.3.8 String.prototype.includes ( searchString [ ,
position ] )
调用此方法时执行以下步骤:
1. 让 O 为 ? RequireObjectCoercible (this
值)。
2. 让 S 为 ? ToString (O ).
3. 让 isRegExp 为 ? IsRegExp (searchString ).
4. 如果 isRegExp 为 true ,抛出
TypeError 异常。
5. 让 searchStr 为 ? ToString (searchString ).
6. 让 pos 为 ? ToIntegerOrInfinity (position ).
7. Assert : 如果 position 为
undefined ,则 pos 为 0。
8. 让 len 为 S 的长度。
9. 让 start 为将 pos 限制在 0 和 len
之间的结果。
10. 让 index 为 StringIndexOf (S ,
searchStr , start ).
11. 如果 index ≠ -1,返回 true 。
12. 返回 false 。
注 1
如果 searchString 作为一个 substring 出现在将该对象转换为字符串的结果中,且出现在一个或多个大于或等于
position 的索引位置上,则此函数返回 true ;否则返回 false 。如果
position 为 undefined ,则假定为 0,以便搜索整个字符串。
注 2
如果第一个参数是 RegExp,则抛出异常的规定是为了允许将来版本定义扩展,允许这样的参数值。
注 3
此方法具有通用性;它不要求其 this 值是一个字符串对象。因此,它可以转移到其他类型的对象中用作方法。
22.1.3.9 String.prototype.indexOf ( searchString [ ,
position ] )
注 1
如果 searchString 作为一个 substring 出现在将该对象转换为字符串的结果中,且出现在一个或多个大于或等于
position 的索引位置上,则返回最小的这样的索引;否则,返回 -1 𝔽 。如果 position
为 undefined ,则假定为 +0 𝔽 ,以便搜索整个字符串。
调用此方法时执行以下步骤:
1. 让 O 为 ? RequireObjectCoercible (this
值)。
2. 让 S 为 ? ToString (O ).
3. 让 searchStr 为 ? ToString (searchString ).
4. 让 pos 为 ? ToIntegerOrInfinity (position ).
5. Assert : 如果 position 为
undefined ,则 pos 为 0。
6. 让 len 为 S 的长度。
7. 让 start 为将 pos 限制在 0 和 len
之间的结果。
8. 返回 𝔽 (StringIndexOf (S ,
searchStr , start )).
注 2
此方法具有通用性;它不要求其 this 值是一个字符串对象。因此,它可以转移到其他类型的对象中用作方法。
22.1.3.10 String.prototype.isWellFormed ( )
调用此方法时执行以下步骤:
1. 让 O 为 ? RequireObjectCoercible (this
值)。
2. 让 S 为 ? ToString (O ).
3. 返回 IsStringWellFormedUnicode (S ).
22.1.3.11 String.prototype.lastIndexOf ( searchString [ ,
position ] )
Note 1
如果 searchString 作为一个 子字符串 出现在将此对象转换为字符串的结果中,且出现的位置小于或等于
position ,则返回最大的这样的索引;否则,返回 -1 𝔽 。如果 position 为
undefined ,则假设字符串的长度,以便搜索整个字符串。
调用此方法时执行以下步骤:
1. 让 O 为 ? RequireObjectCoercible (this
值)。
2. 让 S 为 ? ToString (O ).
3. 让 searchStr 为 ? ToString (searchString ).
4. 让 numPos 为 ? ToNumber (position ).
5. Assert :如果 position 为
undefined ,则 numPos 为 NaN 。
6. 如果 numPos 为 NaN ,则让 pos 为
+∞;否则,让 pos 为 ! ToIntegerOrInfinity (numPos )。
7. 让 len 为 S 的长度。
8. 让 searchLen 为 searchStr 的长度。
9. 让 start 为 clamping
pos 在 0 和 len - searchLen 之间的结果。
10. 如果 searchStr 是空字符串,则返回 𝔽 (start )。
11. 对于每个 整数 i 使得 0 ≤ i ≤
start ,按降序执行
a. 让 candidate 为 substring 从
i 到 i + searchLen 的 S 。
b. 如果 candidate 是 searchStr ,则返回 𝔽 (i )。
12. 返回 -1 𝔽 。
Note 2
此方法有意是通用的;它不要求其 this 值为字符串对象。因此,它可以转移到其他类型的对象上作为方法使用。
22.1.3.12 String.prototype.localeCompare ( that [ ,
reserved1 [ , reserved2 ] ] )
一个包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范实现此方法。如果 ECMAScript 实现不包含 ECMA-402
API,则使用以下规范来实现此方法:
此方法返回一个除 NaN 以外的数字,表示将 this 值(转换为字符串 S )与
that (转换为字符串 thatValue )进行的一个 实现定义的
与区域设置相关的字符串比较的结果。结果旨在与根据 排序顺序 符合 宿主环境 当前区域设置的字符串值,并且当
S 排在 thatValue 之前时为负,当 S 排在 thatValue 之后时为正,在其他情况下为零(表示
S 和 thatValue 之间没有相对顺序)。
在执行比较之前,此方法执行以下步骤以准备字符串:
1. 让 O 为 ? RequireObjectCoercible (this
值)。
2. 让 S 为 ? ToString (O ).
3. 让 thatValue 为 ? ToString (that ).
此方法的第二和第三个参数的含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得对这些参数位置赋予任何其他解释。
实际的返回值是 实现定义的 ,以允许在其中编码额外的信息,但当此方法被视为两个参数的方法时,必须是一个
一致的比较器 ,在所有字符串集合上定义一个全序。此方法还必须识别和遵守
Unicode 标准中的规范等价性,包括在比较可区分的字符串时返回 +0 𝔽 。
Note 1
此方法本身不适合作为 Array.prototype.sort
的参数,因为后者要求一个具有两个参数的函数。
Note 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 标准附录
#15,Unicode 规范化形式 和 Unicode 技术说明 #5,应用中的规范等价性 。还请参见
Unicode 技术标准 #10,Unicode 排序算法 。
建议此方法不应遵守 Unicode 兼容等价或兼容分解,如 Unicode 标准第 3 章第 3.7 节中定义的。
Note 3
此方法有意是通用的;它不要求其 this 值为字符串对象。因此,它可以转移到其他类型的对象上作为方法使用。
22.1.3.13 String.prototype.match ( regexp )
当调用此方法时,它执行以下步骤:
1. 让 O 为 ? RequireObjectCoercible (this
值)。
2. 如果 regexp 既不是 undefined
也不是 null ,则
a. 让 matcher 为 ? GetMethod (regexp , @@match ).
b. 如果 matcher 不是 undefined ,
则
i. 返回 ? Call (matcher , regexp , «
O »).
3. 让 S 为 ? ToString (O ).
4. 让 rx 为 ? RegExpCreate (regexp ,
undefined ).
5. 返回 ? Invoke (rx , @@match , «
S »).
Note
此方法有意是通用的;它不要求其 this 值为字符串对象。因此,它可以转移到其他类型的对象上作为方法使用。
22.1.3.14 String.prototype.matchAll ( regexp )
此方法对表示 this 值的字符串执行正则表达式匹配,并返回一个迭代器。每次迭代结果的值是一个数组,包含匹配结果;如果字符串不匹配,则返回
null 。
当调用此方法时,它执行以下步骤:
1. 让 O 为 ? RequireObjectCoercible (this
值)。
2. 如果 regexp 既不是 undefined
也不是 null ,则
a. 让 isRegExp 为 ? IsRegExp (regexp ).
b. 如果 isRegExp 为 true ,则
i. 让 flags 为 ? Get (regexp , "flags" ).
ii. 执行 ? RequireObjectCoercible (flags ).
iii. 如果 ? ToString (flags ) 不包含
"g" ,则抛出 TypeError 异常。
c. 让 matcher 为 ? GetMethod (regexp , @@matchAll ).
d. 如果 matcher 不是 undefined ,
则
i. 返回 ? Call (matcher , regexp , «
O »).
3. 让 S 为 ? ToString (O ).
4. 让 rx 为 ? RegExpCreate (regexp , "g" ).
5. 返回 ? Invoke (rx , @@matchAll , «
S »).
Note 1
此方法有意是通用的;它不要求其 this 值为字符串对象。因此,它可以转移到其他类型的对象上作为方法使用。
Note 2
与 String.prototype.split
类似,String.prototype.matchAll
设计时通常不修改其输入。
22.1.3.15 String.prototype.normalize ( [ form ] )
当调用此方法时,它执行以下步骤:
1. 让 O 为 ? RequireObjectCoercible (this
值)。
2. 让 S 为 ? ToString (O ).
3. 如果 form 为 undefined ,则让 f
为 "NFC" 。
4. 否则,让 f 为 ? ToString (form ).
5. 如果 f
不是以下之一:"NFC" 、"NFD" 、"NFKC" 或
"NFKD" ,则抛出 RangeError 异常。
6. 让 ns 为将 S 规范化为由 f
指定的规范化形式的字符串值,如 最新的 Unicode 标准,规范化形式
所述。
7. 返回 ns 。
Note
此方法有意是通用的;它不要求其 this 值为字符串对象。因此,它可以转移到其他类型的对象上作为方法使用。
22.1.3.16 String.prototype.padEnd ( maxLength [ ,
fillString ] )
当调用此方法时,它执行以下步骤:
1. 让 O 为 ? RequireObjectCoercible (this
值)。
2. 返回 ? StringPaddingBuiltinsImpl (O ,
maxLength ,
fillString , end ).
22.1.3.17 String.prototype.padStart ( maxLength [ ,
fillString ] )
当调用此方法时,它执行以下步骤:
1. 让 O 为 ? RequireObjectCoercible (this
值)。
2. 返回 ? StringPaddingBuiltinsImpl (O ,
maxLength ,
fillString , start ).
22.1.3.17.1 StringPaddingBuiltinsImpl ( O ,
maxLength , fillString , placement )
抽象操作 StringPaddingBuiltinsImpl 接受参数 O (一个 ECMAScript
语言值 ),maxLength (一个 ECMAScript
语言值 ),fillString (一个 ECMAScript
语言值 ),和 placement (start 或
end ),并返回一个 String。它执行以下步骤:
1. 让 S 为 ? ToString (O ).
2. 让 intMaxLength 为 ℝ (? ToLength (maxLength )).
3. 让 stringLength 为 S 的长度。
4. 如果 intMaxLength ≤ stringLength ,返回
S 。
5. 如果 fillString 为 undefined ,将
fillString 设置为仅包含代码单元 0x0020(空格)的字符串。
6. 否则,将 fillString 设置为 ? ToString (fillString ).
7. 返回 StringPad (S ,
intMaxLength , fillString , placement ).
22.1.3.17.2 StringPad ( S , maxLength ,
fillString , placement )
抽象操作 StringPad 接受参数 S (一个字符串)、maxLength (一个非负的 整数 )、fillString (一个字符串)和
placement (start 或 end ),并返回一个字符串。它执行以下步骤:
1. 让 stringLength 为 S 的长度。
2. 如果 maxLength ≤ stringLength ,返回
S 。
3. 如果 fillString 是空字符串,返回 S 。
4. 让 fillLen 为 maxLength -
stringLength 。
5. 让 truncatedStringFiller 为由重复连接的
fillString 组成的字符串,长度截断为 fillLen 。
6. 如果 placement 为 start ,返回
truncatedStringFiller 和 S 的 字符串连接 。
7. 否则,返回 S 和 truncatedStringFiller 的
字符串连接 。
注 1
参数 maxLength 会被限制,使其不小于 S 的长度。
注 2
参数 fillString 默认为 " " (由代码单元 0x0020 空格组成的字符串)。
22.1.3.17.3 ToZeroPaddedDecimalString ( n ,
minLength )
抽象操作 ToZeroPaddedDecimalString 接受参数 n (一个非负的 整数 )和 minLength (一个非负的 整数 ),并返回一个字符串。它执行以下步骤:
1. 让 S 为 n 的字符串表示,格式为十进制数字。
2. 返回 StringPad (S ,
minLength , "0" , start ).
22.1.3.18 String.prototype.repeat ( count )
当调用此方法时,它执行以下步骤:
1. 让 O 为 ? RequireObjectCoercible (this
值)。
2. 让 S 为 ? ToString (O ).
3. 让 n 为 ? ToIntegerOrInfinity (count ).
4. 如果 n < 0 或 n = +∞,抛出一个
RangeError 异常。
5. 如果 n = 0,返回空字符串。
6. 返回由 n 个 S 的副本连接而成的字符串。
注 1
此方法创建一个字符串,该字符串由 this 值(转换为字符串)重复 count 次。
注 2
此方法具有通用性;它不要求其 this 值是字符串对象。因此,它可以转移到其他类型的对象中用作方法。
22.1.3.19 String.prototype.replace ( searchValue ,
replaceValue )
调用此方法时,会执行以下步骤:
1. 让 O 为 ? RequireObjectCoercible (this
值)。
2. 如果 searchValue 既不是
undefined
也不是 null ,则
a. 让 replacer 为 ? GetMethod (searchValue , @@replace ).
b. 如果 replacer 不为
undefined ,
则
i. 返回 ? Call (replacer , searchValue , «
O , replaceValue »).
3. 让 string 为 ? ToString (O ).
4. 让 searchString 为 ? ToString (searchValue ).
5. 让 functionalReplace 为 IsCallable (replaceValue ).
6. 如果 functionalReplace 为 false ,
则
a. 将 replaceValue 设置为 ? ToString (replaceValue ).
7. 让 searchLength 为 searchString 的长度。
8. 让 position 为 StringIndexOf (string ,
searchString , 0).
9. 如果 position = -1,返回 string 。
10. 让 preceding 为 substring of
string 从 0 到 position 。
11. 让 following 为 substring of
string 从 position + searchLength 。
12. 如果 functionalReplace 为 true ,
则
a. 让 replacement 为 ? ToString (? Call (replaceValue ,
undefined ,
« searchString , 𝔽 (position ),
string »)).
13. 否则,
a. Assert : replaceValue
是一个
String 。
b. 让 captures 为一个新的空 List 。
c. 让 replacement 为 ! GetSubstitution (searchString ,
string , position , captures , undefined ,
replaceValue ).
14. 返回 字符串连接 的
preceding 、replacement 和 following 。
注
此方法是有意设计为通用的;它不要求其 this 值必须是一个 String 对象。因此,它可以转移到其他类型的对象上用作方法。
22.1.3.19.1 GetSubstitution ( matched , str ,
position , captures , namedCaptures , replacementTemplate )
抽象操作 GetSubstitution 接受以下参数:matched (一个字符串),str (一个字符串),position (一个非负的
整数 ),captures (一个 列表 ,其中元素可以是字符串或
undefined ),namedCaptures (一个对象或 undefined ),和
replacementTemplate (一个字符串),并返回一个要么是包含字符串的 正常完成 ,要么是一个
抛出完成 。在此抽象操作中,十进制数字
是从 0x0030(数字零)到 0x0039(数字九)的代码单元。调用时执行以下步骤:
1. 令 stringLength 为 str 的长度。
2. 断言 : position ≤
stringLength .
3. 令 result 为一个空字符串。
4. 令 templateRemainder 为
replacementTemplate 。
5. 重复以下操作,直到 templateRemainder 变为空字符串,
a. 注:以下步骤将
ref (templateRemainder 的前缀)隔离出来,确定 refReplacement
(其替代品),然后将该替代品追加到 result 。
b. 如果 templateRemainder 以 "$$"
开头,则
i. 令 ref 为 "$$" 。
ii. 令 refReplacement 为 "$" 。
c. 否则,如果 templateRemainder 以
"$`" 开头,则
i. 令 ref 为 "$`" 。
ii. 令 refReplacement 为 str 的子字符串,从 0 到
position 。
d. 否则,如果 templateRemainder 以
"$&" 开头,则
i. 令 ref 为 "$&" 。
ii. 令 refReplacement 为 matched 。
e. 否则,如果 templateRemainder 以
"$'" (0x0024(美元符号)后跟 0x0027(撇号))开头,则
i. 令 ref 为 "$'" 。
ii. 令 matchLength 为 matched 的长度。
iii. 令 tailPos 为 position +
matchLength 。
iv. 令 refReplacement 为 str 的子字符串,从 min (tailPos ,
stringLength )。
v. 注:tailPos 可能会超出
stringLength ,仅当该抽象操作通过对一个对象的 @@replace
方法的调用而触发,该对象的 "exec" 属性不是原生的 %RegExp.prototype.exec% 时。
f. 否则,如果 templateRemainder 以 "$"
后跟 1 个或多个十进制数字开头,则
i. 如果 templateRemainder 以
"$" 后跟 2 个或更多十进制数字开头,则令 digitCount 为 2。否则,令
digitCount 为 1。
ii. 令 digits 为 templateRemainder 的子字符串,从 1 到
1 + digitCount 。
iii. 令 index 为 number (digits ),转换为十进制。
iv. 如果 index 为 0,则
i. 令 ref 为 "$0" 。
ii. 令 refReplacement 为 matched 。
v. 否则,如果 index 大于 captures 的长度,则
i. 令 ref 为 "$" 加上
index 的字符串。
ii. 令 refReplacement 为
"" 。
vi. 否则,如果 index 大于 0 且小于或等于 captures
的长度,则
i. 令 ref 为 "$" 加上
index 的字符串。
ii. 令 refReplacement 为 captures [index - 1]。
g. 否则,如果 templateRemainder 以 "$"
后跟 1 个字符开头且该字符不是十进制数字开头,则
i. 令 ref 为 templateRemainder 的第一个字符。
ii. 令 refReplacement 为 "$"
加上 ref 。
h. 否则,令 ref 为 templateRemainder
的第一个字符。
i. 令 templateRemainder 为 templateRemainder 的子字符串,从
ref 的长度到结尾。
6. 返回正常完成并且 result 为完成的值。
注: 术语 十进制数字 是从 0x0030(数字零)到 0x0039(数字九)的代码单元。对于字母的拼写可以参考
[ECMA-262][https://www.ecma-international.org/en-GB/standards/ecma-262/]
22.1.3.20 String.prototype.replaceAll ( searchValue ,
replaceValue )
当调用此方法时,它执行以下步骤:
1. 让 O 为 ? RequireObjectCoercible (this
值)。
2. 如果 searchValue 既不是
undefined
也不是 null ,那么
a. 让 isRegExp 为 ? IsRegExp (searchValue )。
b. 如果 isRegExp 为 true ,那么
i. 让 flags 为 ? Get (searchValue ,
"flags" ).
ii. 执行 ? RequireObjectCoercible (flags ).
iii. 如果 ? ToString (flags ) 不包含
"g" ,抛出一个 TypeError 异常。
c. 让 replacer 为 ? GetMethod (searchValue , @@replace ).
d. 如果 replacer 不是
undefined ,
那么
i. 返回 ? Call (replacer , searchValue , «
O , replaceValue »).
3. 让 string 为 ? ToString (O ).
4. 让 searchString 为 ? ToString (searchValue ).
5. 让 functionalReplace 为 IsCallable (replaceValue ).
6. 如果 functionalReplace 为 false ,
那么
a. 将 replaceValue 设置为 ? ToString (replaceValue ).
7. 让 searchLength 为 searchString 的长度。
8. 让 advanceBy 为 max (1,
searchLength )。
9. 让 matchPositions 为一个新的空 List 。
10. 让 position 为 StringIndexOf (string ,
searchString , 0).
11. 重复,直到 position ≠ -1,
a. 将 position 添加到 matchPositions 中。
b. 将 position 设置为 StringIndexOf (string ,
searchString , position + advanceBy ).
12. 让 endOfLastMatch 为 0。
13. 让 result 为空字符串。
14. 对于 matchPositions 中的每个元素 p ,
执行
a. 让 preserved 为 substring 的
string 从 endOfLastMatch 到 p 部分。
b. 如果 functionalReplace 为
true ,
那么
i. 让 replacement 为 ? ToString (? Call (replaceValue ,
undefined , « searchString , 𝔽 (p ),
string »)).
c. 否则,
i. Assert : replaceValue
是一个
字符串 。
ii. 让 captures 为一个新的空 List 。
iii. 让 replacement 为 ! GetSubstitution (searchString ,
string , p , captures , undefined ,
replaceValue ).
d. 将 result 设置为 string-concatenation
的 result 、preserved 和 replacement 的连接。
e. 将 endOfLastMatch 设置为 p +
searchLength 。
15. 如果 endOfLastMatch 小于 string 的长度,
那么
a. 将 result 设置为 string-concatenation
的 result 和 substring 的 string
从 endOfLastMatch 开始部分。
16. 返回 result 。
22.1.3.21 String.prototype.search ( regexp )
当调用此方法时,它执行以下步骤:
1. 让 O 为 ? RequireObjectCoercible (this
值)。
2. 如果 regexp 既不是 undefined
也不是 null ,那么
a. 让 searcher 为 ? GetMethod (regexp , @@search ).
b. 如果 searcher 不是 undefined ,
那么
i. 返回 ? Call (searcher , regexp , «
O »).
3. 让 string 为 ? ToString (O ).
4. 让 rx 为 ? RegExpCreate (regexp ,
undefined ).
5. 返回 ? Invoke (rx , @@search ,
«
string »).
注
此方法有意设计为通用的;它不要求其 this 值必须是一个字符串对象。因此,它可以被转移到其他类型的对象上用作方法。
22.1.3.22 String.prototype.slice ( start , end )
此方法返回将该对象转换为字符串后,从索引 start 开始到索引 end (不包括 end 索引,或者如果 end 为
undefined 则到字符串的末尾)的 子字符串 。如果 start 为负数,则将其视为
sourceLength + start ,其中 sourceLength
是字符串的长度。如果 end 为负数,则将其视为 sourceLength +
end ,其中 sourceLength 是字符串的长度。结果是一个 字符串
值,而不是一个字符串对象。
当调用此方法时,它执行以下步骤:
1. 让 O 为 ? RequireObjectCoercible (this
值)。
2. 让 S 为 ? ToString (O ).
3. 让 len 为 S 的长度。
4. 让 intStart 为 ? ToIntegerOrInfinity (start ).
5. 如果 intStart = -∞,让 from 为 0。
6. 否则如果 intStart < 0, let from 为
max (len +
intStart , 0).
7. 否则, let from 为 min (intStart ,
len ).
8. 如果 end 为 undefined ,让
intEnd 为 len ;否则让 intEnd 为 ? ToIntegerOrInfinity (end ).
9. 如果 intEnd = -∞,让 to 为 0。
10. 否则如果 intEnd < 0, let to 为
max (len +
intEnd , 0).
11. 否则, let to 为 min (intEnd ,
len ).
12. 如果 from ≥ to ,返回空字符串。
13. 返回 子字符串 从 from 到 to 的
S 。
注
此方法有意设计为通用的;它不要求其 this 值必须是一个字符串对象。因此,它可以被转移到其他类型的对象上用作方法。
22.1.3.23 String.prototype.split ( separator , limit )
该方法返回一个数组,其中包含将转换为字符串的对象的子串。子串是通过从左到右搜索separator 的出现位置来确定的,这些出现位置不属于返回数组中的任何字符串,而是用来划分字符串值。separator 的值可以是任意长度的字符串,或具有@@split 方法的对象,如正则表达式。
调用时执行以下步骤:
1. 让O 等于 ? RequireObjectCoercible (this 值)。
2.
如果separator 既不是undefined 也不是null ,则:
a. 让splitter 等于 ? GetMethod (separator , @@split )。
b. 如果splitter 不是undefined ,则:
i. 返回 ? Call (splitter , separator ,
«O , limit »)。
3. 让S 等于 ? ToString (O )。
4.
如果limit 是undefined ,则让lim 等于 2** 32 - 1;否则让lim 等于 ℝ (? ToUint32 (limit ))。
5. 让R 等于 ? ToString (separator )。
6. 如果lim = 0,则:
a. 返回 CreateArrayFromList (« »)。
7. 如果separator 是undefined ,则:
a. 返回 CreateArrayFromList («S »)。
8. 让separatorLength 等于R 的长度。
9. 如果separatorLength = 0,则:
a. 让head 等于substring 的S 从 0 到
lim 。
b. 让codeUnits 等于一个List ,包含head 的代码单元序列。
c. 返回 CreateArrayFromList (codeUnits )。
10. 如果S 是空字符串,则返回 CreateArrayFromList («S »)。
11. 让substrings 等于一个新的空List 。
12. 让i 等于 0。
13. 让j 等于 StringIndexOf (S ,
R , 0)。
14. 重复,直到j = -1:
a. 让T 等于substring 的S 从 i
到 j 。
b. 将T 附加到substrings 。
c. 如果substrings 中的元素数量等于lim ,返回 CreateArrayFromList (substrings )。
d. 将i 设置为j + separatorLength 。
e. 将j 设置为 StringIndexOf (S ,
R , i )。
15. 让T 等于substring 的S 从 i 开始。
16. 将T 附加到substrings 。
17. 返回 CreateArrayFromList (substrings )。
注 1
separator 的值可以是空字符串。在这种情况下,separator 不会匹配输入字符串开头或结尾的空子串 ,也不会匹配前一个分隔符匹配后的空子串 。如果separator 是空字符串,则字符串会被拆分为单个代码单元元素;结果数组的长度等于字符串的长度,每个子串 包含一个代码单元。
如果this 值是(或转换为)空字符串,则结果取决于separator 是否能匹配空字符串。如果可以,则结果数组不包含任何元素。否则,结果数组包含一个元素,即空字符串。
如果separator 是undefined ,则结果数组只包含一个字符串,即this 值(转换为字符串)。如果limit 不是undefined ,则输出数组会被截断,使其不包含超过limit 个元素。
注 2
该方法有意是通用的;它不要求其this 值必须是一个字符串对象。因此,它可以被转移到其他类型的对象上作为方法使用。
22.1.3.24 String.prototype.startsWith ( searchString [ ,
position ] )
当调用时,该方法执行以下步骤:
1. 让 O 等于 ? RequireObjectCoercible (this
值)。
2. 让 S 等于 ? ToString (O )。
3. 让 isRegExp 等于 ? IsRegExp (searchString )。
4. 如果 isRegExp 为 true ,则抛出一个
TypeError 异常。
5. 让 searchStr 等于 ? ToString (searchString )。
6. 让 len 等于 S 的长度。
7. 如果 position 是 undefined ,则让
pos 等于 0;否则让 pos 等于 ? ToIntegerOrInfinity (position )。
8. 让 start 等于将 pos 限制在 0 和 len
之间的结果。
9. 让 searchLength 等于 searchStr 的长度。
10. 如果 searchLength = 0,返回 true 。
11. 让 end 等于 start + searchLength 。
12. 如果 end > len ,返回
false 。
13. 让 substring 等于 substring 的
S 从 start 到 end 。
14. 如果 substring 等于 searchStr ,返回
true 。
15. 返回 false 。
Note 1
如果将 searchString 转换为字符串后的代码单元序列与该对象(转换为字符串)从索引 position 开始的对应代码单元序列相同,则此方法返回
true 。否则返回 false 。
Note 2
如果第一个参数是 RegExp,则抛出异常是为了允许未来版本定义允许这种参数值的扩展。
Note 3
该方法有意是通用的;它不要求其 this 值必须是一个字符串对象。因此,它可以被转移到其他类型的对象上作为方法使用。
22.1.3.25 String.prototype.substring ( start , end )
此方法返回将此对象转换为字符串的结果的一个 substring ,从索引 start 开始,到索引
end (但不包括该索引)为止(如果 end 是 undefined ,则一直到字符串的末尾)。结果是一个 String
值,而不是一个字符串对象。
如果任一参数是 NaN 或负值,则替换为零;如果任一参数严格大于字符串的长度,则替换为字符串的长度。
如果 start 严格大于 end ,则交换它们。
调用时执行以下步骤:
1. 让 O 等于 ? RequireObjectCoercible (this
值)。
2. 让 S 等于 ? ToString (O )。
3. 让 len 等于 S 的长度。
4. 让 intStart 等于 ? ToIntegerOrInfinity (start )。
5. 如果 end 是 undefined ,则让
intEnd 等于 len ;否则让 intEnd 等于 ? ToIntegerOrInfinity (end )。
6. 让 finalStart 等于将 intStart 限制在 0 和
len 之间的结果。
7. 让 finalEnd 等于将 intEnd 限制在 0 和
len 之间的结果。
8. 让 from 等于 min (finalStart ,
finalEnd )。
9. 让 to 等于 max (finalStart ,
finalEnd )。
10. 返回 substring 的 S 从
from 到 to 。
Note
该方法有意是通用的;它不要求其 this 值必须是一个字符串对象。因此,它可以被转移到其他类型的对象上作为方法使用。
22.1.3.26 String.prototype.toLocaleLowerCase ( [ reserved1 [ ,
reserved2 ] ] )
一个包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范中的规定来实现此方法。如果 ECMAScript 实现不包含 ECMA-402 API,则使用以下规范:
该方法将字符串值解释为 UTF-16 编码的代码点序列,如 6.1.4 中所描述。
它的工作方式与 toLowerCase
完全相同,只是它旨在产生符合 宿主环境
当前语言环境约定的区域敏感结果。在少数情况下(例如土耳其语),当该语言的规则与常规 Unicode 大小写映射冲突时,将会有差异。
此方法的可选参数的含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得将这些参数位置用于其他目的。
Note
该方法有意是通用的;它不要求其 this 值必须是一个字符串对象。因此,它可以被转移到其他类型的对象上作为方法使用。
22.1.3.27 String.prototype.toLocaleUpperCase ( [ reserved1 [ ,
reserved2 ] ] )
一个包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范中的规定来实现此方法。如果 ECMAScript 实现不包含 ECMA-402 API,则使用以下规范:
该方法将字符串值解释为 UTF-16 编码的代码点序列,如 6.1.4 中所描述。
它的工作方式与 toUpperCase
完全相同,只是它旨在产生符合 宿主环境
当前语言环境约定的区域敏感结果。在少数情况下(例如土耳其语),当该语言的规则与常规 Unicode 大小写映射冲突时,将会有差异。
此方法的可选参数的含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得将这些参数位置用于其他目的。
Note
该方法有意是通用的;它不要求其 this 值必须是一个字符串对象。因此,它可以被转移到其他类型的对象上作为方法使用。
22.1.3.28 String.prototype.toLowerCase ( )
此方法将字符串值解释为 UTF-16 编码的代码点序列,如 6.1.4 中所描述。
调用时执行以下步骤:
1. 令 O 为 ? RequireObjectCoercible (this
值)。
2. 令 S 为 ? ToString (O ).
3. 令 sText 为 StringToCodePoints (S )。
4. 令 lowerText 为根据 Unicode 默认大小写转换算法的
toLowercase(sText ) 结果。
5. 令 L 为 CodePointsToString (lowerText )。
6. 返回 L 。
结果必须根据 Unicode 字符数据库中的区域无关大小写映射生成(这明确包括不仅仅是文件 UnicodeData.txt
,还包括伴随的文件
SpecialCasing.txt
中所有区域无关的映射)。
Note 1
某些代码点的大小写映射可能产生多个代码点。在这种情况下,结果字符串的长度可能与源字符串不同。由于 toUpperCase
和 toLowerCase
都具有上下文敏感行为,因此这些方法并不对称。换句话说,s.toUpperCase().toLowerCase()
不一定等于
s.toLowerCase()
。
Note 2
该方法有意是通用的;它不要求其 this 值必须是一个字符串对象。因此,它可以被转移到其他类型的对象上作为方法使用。
22.1.3.29 String.prototype.toString ( )
调用此方法时执行以下步骤:
1. 返回 ? ThisStringValue (this
值)。
Note
对于 String 对象,此方法恰好返回与 valueOf
方法相同的结果。
22.1.3.30 String.prototype.toUpperCase ( )
此方法将字符串值解释为 UTF-16 编码的代码点序列,如 6.1.4 中所描述。
它的行为与 String.prototype.toLowerCase
完全相同,只不过字符串使用 Unicode 默认大小写转换算法中的 toUppercase 算法进行映射。
Note
该方法有意是通用的;它不要求其 this 值必须是一个字符串对象。因此,它可以被转移到其他类型的对象上作为方法使用。
22.1.3.31 String.prototype.toWellFormed ( )
此方法返回一个字符串表示形式,其中所有未构成有效 前导代理项 和 尾随代理项 (未成为有效的 代理对 )都被替换为 U+FFFD(替代字符)。
调用时执行以下步骤:
1. 让 O 为 ? RequireObjectCoercible (this
值)。
2. 让 S 为 ? ToString (O ).
3. 让 strLen 为 S 的长度。
4. 让 k 为 0。
5. 让 result 为空字符串。
6. 重复执行,直到 k < strLen ,
a. 让 cp 为 CodePointAt (S ,
k ).
b. 如果 cp .[[IsUnpairedSurrogate]] 为 true ,则
i. 将 result 设置为 result 和
0xFFFD(替代字符)的连接。
c. 否则,
i. 将 result 设置为 result 和 UTF16EncodeCodePoint (cp .[[CodePoint]] ) 的连接。
d. 将 k 设置为 k + cp .[[CodeUnitCount]] 。
7. 返回 result 。
22.1.3.32 String.prototype.trim ( )
此方法将字符串值解释为一系列 UTF-16 编码的代码点,如 6.1.4 中所述。
调用时执行以下步骤:
1. 让 S 为 this 值。
2. 返回 ? TrimString (S , start+end ).
Note
此方法故意设计得很通用;它不要求其 this 值是一个字符串对象。因此,它可以转移到其他类型的对象上作为方法使用。
22.1.3.32.1 TrimString ( string , where )
抽象操作 `TrimString` 接受参数 string (一个 ECMAScript
语言值 )和 where (start 、end ,或
start+end ),并返回一个 正常完成记录
中的字符串或一个 异常完成记录 。它将
string 解释为一系列 UTF-16 编码的代码点,如 6.1.4
中所述。调用时执行以下步骤:
1. 让 str 为 ? RequireObjectCoercible (string ).
2. 让 S 为 ? ToString (str ).
3. 如果 where 是 start ,则
a. 让 T 为一个副本,其中 S 的前导空白被去除。
4. 否则,如果 where 是 end ,则
a. 让 T 为一个副本,其中 S 的尾随空白被去除。
5. 否则,
a. Assert :where 是
start+end 。
b. 让 T 为一个副本,其中 S 的前导和尾随空白都被去除。
6. 返回 T 。
空白的定义是 WhiteSpace 和 LineTerminator
的并集。在确定 Unicode 代码点是否在 Unicode 一般类别“Space_Separator”(“Zs”)中时,代码单元序列被解释为 UTF-16 编码的代码点序列,如 6.1.4 中所述。
22.1.3.33 String.prototype.trimEnd ( )
此方法将字符串值解释为一系列 UTF-16 编码的代码点,如 6.1.4 中所述。
调用时执行以下步骤:
1. 让 S 为 this 值。
2. 返回 ? TrimString (S , end ).
Note
此方法故意设计得很通用;它不要求其 this 值是一个字符串对象。因此,它可以转移到其他类型的对象上作为方法使用。
22.1.3.34 String.prototype.trimStart ( )
此方法将字符串值解释为一系列 UTF-16 编码的代码点,如 6.1.4 中所述。
调用时执行以下步骤:
1. 让 S 为 this 值。
2. 返回 ? TrimString (S , start ).
Note
此方法故意设计得很通用;它不要求其 this 值是一个字符串对象。因此,它可以转移到其他类型的对象上作为方法使用。
22.1.3.35 String.prototype.valueOf ( )
当调用此方法时,执行以下步骤:
1. 返回 ? ThisStringValue (this
值)。
22.1.3.35.1 ThisStringValue ( value )
抽象操作 `ThisStringValue` 接受参数 value (一个 ECMAScript
语言值 )并返回一个 正常完成的
字符串或一个 抛出完成的 。它执行以下步骤:
1. 如果 value 是一个字符串 ,则返回
value 。
2. 如果 value 是一个对象 并且
value 有一个 [[StringData]] 内部槽,则
a. 令 s 为 value .[[StringData]] 。
b. 断言 : s 是一个字符串 。
c. 返回 s 。
3. 抛出一个 TypeError 异常。
22.1.3.36 String.prototype [ @@iterator ] ( )
此方法返回一个迭代器对象(27.1.1.2 ),该对象遍历字符串值的代码点,逐个返回每个代码点作为字符串值。
当调用此方法时,执行以下步骤:
1. 令 O 为 ? RequireObjectCoercible (this
值)。
2. 令 s 为 ? ToString (O ).
3. 令 closure 为一个新的 抽象闭包 ,没有参数,捕获
s 并执行以下步骤:
a. 令 len 为 s 的长度。
b. 令 position 为 0。
c. 重复,直到 position 小于 len ,
i. 令 cp 为 CodePointAt (s ,
position )。
ii. 令 nextIndex 为 position +
cp .[[CodeUnitCount]] 。
iii. 令 resultString 为 substring 从
position 到 nextIndex 的 s 。
iv. 将 position 设置为 nextIndex 。
v. 执行 ? GeneratorYield (CreateIterResultObject (resultString ,
false ))。
d. 返回 undefined 。
4. 返回 CreateIteratorFromClosure (closure ,
"%StringIteratorPrototype%" , %StringIteratorPrototype% )。
此方法的 "name" 属性的值为 "[Symbol.iterator]" 。
22.1.4 字符串实例的属性
字符串实例是 字符串特性对象 ,并具有为这种对象指定的内部方法。字符串实例从
字符串原型对象
继承属性。字符串实例还具有一个 [[StringData]] 内部槽。[[StringData]]
内部槽是由该字符串对象表示的字符串值。
字符串实例具有一个 "length" 属性,并且有一组可枚举属性,这些属性具有 整数索引 名称。
22.1.4.1 length
表示此字符串对象所代表的字符串值中的元素数量。
一旦字符串对象被初始化,此属性将保持不变。它的属性为 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
false }。
22.1.5 字符串迭代器对象
字符串迭代器是一个对象,表示对某个特定字符串实例对象的特定迭代。字符串迭代器对象没有一个命名的 构造函数 。相反,字符串迭代器对象是通过调用字符串实例对象的某些方法来创建的。
22.1.5.1 %StringIteratorPrototype% 对象
%StringIteratorPrototype% 对象:
22.1.5.1.1 %StringIteratorPrototype%.next ( )
1. 返回 ? GeneratorResume (this
值, empty , "%StringIteratorPrototype%" ).
22.1.5.1.2 %StringIteratorPrototype% [ @@toStringTag ]
@@toStringTag 属性的初始值为字符串值
"String Iterator" 。
该属性的属性为 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] : true }。
22.2 RegExp(正则表达式)对象
一个 RegExp 对象包含一个正则表达式及其关联的标志。
注
正则表达式的形式和功能是模仿 Perl 5 编程语言中的正则表达式功能。
22.2.1 模式
RegExp 构造函数 对输入模式字符串应用以下语法。如果语法无法将字符串解释为模式 的扩展,则会发生错误。
语法
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]
)
(?:
Disjunction [?UnicodeMode,
?UnicodeSetsMode, ?NamedCaptureGroups]
)
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
十六进制尾随代理 对于其关联的 u
十六进制前导代理
的选择是模糊的,应与最接近的可能没有对应的 \u
十六进制前导代理 关联。
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 静态语义:早期错误
注
Pattern ::
Disjunction
QuantifierPrefix
::
{
DecimalDigits
,
DecimalDigits
}
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
)
生成的(
模式字符。
注
调用时执行以下步骤:
1. 断言 :node 是正则表达式模式语法 中的某个生成式的实例。
2. 返回
Atom ::
(
GroupSpecifier opt
Disjunction
)
包含在 node 中的解析节点 的数量。
22.2.1.3 静态语义:CountLeftCapturingParensBefore (node )
抽象操作 CountLeftCapturingParensBefore 接受参数 node (一个 解析节点 ),返回一个非负的整数 。它返回在包含模式中位于 node 左侧的左捕获括号 的数量。
注
调用时执行以下步骤:
1. 断言 :node 是正则表达式模式语法 中的某个生成式的实例。
2. 令 pattern 为包含 node 的Pattern 。
3. 返回
Atom ::
(
GroupSpecifier opt
Disjunction
)
包含在 pattern 中且在 node 之前或包含 node 的解析节点 的数量。
22.2.1.4 静态语义:CapturingGroupNumber
语法指引操作
CapturingGroupNumber 不接受参数,返回一个正的整数 。
注
它在以下生成式中分段定义:
DecimalEscape
::
NonZeroDigit
1. 返回NonZeroDigit 的MV。
DecimalEscape
::
NonZeroDigit
DecimalDigits
1. 令n 为DecimalDigits 中的代码点数量。
2. 返回(NonZeroDigit 的MV ×
10n 加上DecimalDigits 的MV)。
“NonZeroDigit 的MV”和“DecimalDigits 的MV”的定义在12.9.3 。
22.2.1.5 静态语义:IsCharacterClass
语法指引操作
IsCharacterClass 不接受参数,返回一个布尔值。
注
它在以下生成式中分段定义:
ClassAtom ::
-
ClassAtomNoDash
::
SourceCharacter
但不包括\ 或] 或-
ClassEscape
::
b
-
CharacterEscape
1. 返回false 。
ClassEscape
::
CharacterClassEscape
1. 返回true 。
22.2.1.6 静态语义:CharacterValue
语法指引操作
CharacterValue 不接受参数,返回一个非负的整数 。
注 1
它在以下生成式中分段定义:
ClassAtom ::
-
1. 返回 U+002D (HYPHEN-MINUS) 的数值。
ClassAtomNoDash
::
SourceCharacter
但不包括\ 或] 或-
1. 令 ch 为 SourceCharacter 匹配的代码点。
2. 返回 ch 的数值。
ClassEscape
::
b
1. 返回 U+0008 (BACKSPACE) 的数值。
ClassEscape
::
1. 返回 U+002D (HYPHEN-MINUS) 的数值。
CharacterEscape
::
ControlEscape
1. 根据 表65 返回数值。
表65: ControlEscape 代码点值
ControlEscape
数值
代码点
Unicode 名称
符号
t
9
U+0009
CHARACTER TABULATION
<HT>
n
10
U+000A
LINE FEED (LF)
<LF>
v
11
U+000B
LINE TABULATION
<VT>
f
12
U+000C
FORM FEED (FF)
<FF>
r
13
U+000D
CARRIAGE RETURN (CR)
<CR>
CharacterEscape
::
c
AsciiLetter
1. 令 ch 为 AsciiLetter 匹配的代码点。
2. 令 i 为 ch 的数值。
3. 返回 i 除以 32 的余数。
CharacterEscape
::
0
[前瞻不在DecimalDigit 之内]
1. 返回 U+0000 (NULL) 的数值。
注 2
CharacterEscape
::
HexEscapeSequence
1. 返回HexEscapeSequence 的MV。
RegExpUnicodeEscapeSequence
::
u
HexLeadSurrogate
\u
HexTrailSurrogate
1. 令 lead 为 CharacterValue 的HexLeadSurrogate 。
2. 令 trail 为 CharacterValue 的HexTrailSurrogate 。
3. 令 cp 为 UTF16SurrogatePairToCodePoint (lead ,
trail )。
4. 返回 cp 的数值。
RegExpUnicodeEscapeSequence
::
u
Hex4Digits
1. 返回Hex4Digits 的MV。
RegExpUnicodeEscapeSequence
::
u{
CodePoint
}
1. 返回CodePoint 的MV。
HexLeadSurrogate
::
Hex4Digits
HexTrailSurrogate
::
Hex4Digits
HexNonSurrogate
::
Hex4Digits
1. 返回Hex4Digits 的MV。
CharacterEscape
::
IdentityEscape
1. 令 ch 为 IdentityEscape 匹配的代码点。
2. 返回 ch 的数值。
ClassSetCharacter
::
SourceCharacter
但不包括ClassSetSyntaxCharacter
1. 令 ch 为 SourceCharacter 匹配的代码点。
2. 返回 ch 的数值。
ClassSetCharacter
::
\
ClassSetReservedPunctuator
1. 令 ch 为 ClassSetReservedPunctuator
匹配的代码点。
2. 返回 ch 的数值。
ClassSetCharacter
::
\b
1. 返回 U+0008 (BACKSPACE) 的数值。
22.2.1.7 静态语义:MayContainStrings
语法指引操作
MayContainStrings 不接受参数,返回一个布尔值。它在以下生成式中分段定义:
CharacterClassEscape
::
d
D
s
S
w
W
P{
UnicodePropertyValueExpression
}
UnicodePropertyValueExpression
::
UnicodePropertyName
=
UnicodePropertyValue
NestedClass
::
[^
ClassContents
]
ClassContents
::
[empty]
NonemptyClassRanges
ClassSetOperand
::
ClassSetCharacter
1. 返回 false 。
UnicodePropertyValueExpression
::
LoneUnicodePropertyNameOrValue
1. 如果匹配的源文本
LoneUnicodePropertyNameOrValue 是表69 中“属性名称 ”列出的字符串的二进制属性,则返回true 。
2. 返回 false 。
ClassUnion
::
ClassSetRange
ClassUnion opt
1. 如果 ClassUnion 存在,返回MayContainStrings 的ClassUnion 。
2. 返回 false 。
ClassUnion
::
ClassSetOperand
ClassUnion opt
1. 如果MayContainStrings 的ClassSetOperand 为true ,返回true 。
2. 如果ClassUnion 存在,返回MayContainStrings 的ClassUnion 。
3. 返回 false 。
ClassIntersection
::
ClassSetOperand
&&
ClassSetOperand
1. 如果MayContainStrings 的第一个ClassSetOperand 为false ,返回false 。
2. 如果MayContainStrings 的第二个ClassSetOperand 为false ,返回false 。
3. 返回 true 。
ClassIntersection
::
ClassIntersection
&&
ClassSetOperand
1. 如果MayContainStrings 的ClassIntersection 为false ,返回false 。
2. 如果MayContainStrings 的ClassSetOperand 为false ,返回false 。
3. 返回 true 。
ClassSubtraction
::
ClassSetOperand
--
ClassSetOperand
1. 返回MayContainStrings 的第一个ClassSetOperand 。
ClassSubtraction
::
ClassSubtraction
--
ClassSetOperand
1. 返回MayContainStrings 的ClassSubtraction 。
ClassStringDisjunctionContents
::
ClassString
|
ClassStringDisjunctionContents
1. 如果MayContainStrings 的ClassString 为true ,返回true 。
2. 返回MayContainStrings 的ClassStringDisjunctionContents 。
ClassString
::
[empty]
1. 返回 true 。
ClassString
::
NonEmptyClassString
1. 返回MayContainStrings 的NonEmptyClassString 。
NonEmptyClassString
::
ClassSetCharacter
NonEmptyClassString opt
1. 如果NonEmptyClassString 存在,返回true 。
2. 返回 false 。
22.2.1.8 静态语义:匹配的组指定符 ( thisGroupName )
抽象操作 GroupSpecifiersThatMatch 接受参数 thisGroupName (一个 GroupName 解析节点 ),并返回一个 列表 ,包含GroupSpecifier
解析节点 。调用时执行以下步骤:
1. 让 name 为 thisGroupName 的捕获组名 。
2. 让 pattern 为包含 thisGroupName 的模式 。
3. 让 result 为一个新的空列表 。
4. 对于 pattern 包含的每个 组指定符 gs ,执行以下操作:
a. 如果 gs 的捕获组名 是name ,那么
i. 将 gs 添加到 result 。
5. 返回 result 。
22.2.1.9 静态语义:捕获组名
语法导向操作
CapturingGroupName 不接受参数,返回一个字符串。它在以下产生式中逐项定义:
GroupName ::
<
RegExpIdentifierName
>
1. 让 idTextUnescaped 为 RegExp标识符代码点 的
RegExpIdentifierName 。
2. 返回 CodePointsToString (idTextUnescaped )。
22.2.1.10 静态语义:RegExp 标识符代码点
语法导向操作
RegExpIdentifierCodePoints 不接受参数,返回一个代码点的 列表 。它在以下产生式中逐项定义:
RegExpIdentifierName
::
RegExpIdentifierStart
1. 让 cp 为 RegExpIdentifierCodePoint
的 RegExpIdentifierStart 。
2. 返回 « cp »。
RegExpIdentifierName
::
RegExpIdentifierName
RegExpIdentifierPart
1. 让 cps 为 RegExpIdentifierCodePoints
的派生 RegExpIdentifierName 。
2. 让 cp 为 RegExpIdentifierCodePoint
的 RegExpIdentifierPart 。
3. 返回 cps 和 « cp » 的列表连接 。
22.2.1.11 静态语义:RegExp 标识符代码点
语法导向操作
RegExpIdentifierCodePoint 不接受参数,返回一个代码点。它在以下产生式中逐项定义:
RegExpIdentifierStart
::
IdentifierStartChar
1. 返回 IdentifierStartChar 匹配的代码点。
RegExpIdentifierPart
::
IdentifierPartChar
1. 返回 IdentifierPartChar 匹配的代码点。
RegExpIdentifierStart
::
\
RegExpUnicodeEscapeSequence
RegExpIdentifierPart
::
\
RegExpUnicodeEscapeSequence
1. 返回 RegExpUnicodeEscapeSequence
的 CharacterValue
的数值对应的代码点。
RegExpIdentifierStart
::
UnicodeLeadSurrogate
UnicodeTrailSurrogate
RegExpIdentifierPart
::
UnicodeLeadSurrogate
UnicodeTrailSurrogate
1. 让 lead 为 UnicodeLeadSurrogate
匹配的代码点的数值。
2. 让 trail 为 UnicodeTrailSurrogate
匹配的代码点的数值。
3. 返回 UTF16SurrogatePairToCodePoint (lead ,
trail )。
22.2.2 模式语义
正则表达式模式使用下面描述的过程转换为一个 抽象闭包 。鼓励实现使用比下面列出的更高效的算法,只要结果相同。这个
抽象闭包 被用作 RegExp 对象的 [[RegExpMatcher]] 内部槽的值。
如果一个 Pattern 的关联标志不包含
u
或 v
,则它是一个 BMP 模式。否则,它是一个 Unicode 模式。BMP 模式与解释为由一系列 16 位值组成的字符串匹配,这些值是 Unicode
基本多文种平面的代码点。Unicode 模式与解释为由使用 UTF-16 编码的 Unicode 代码点组成的字符串匹配。在描述 BMP 模式行为的上下文中,“字符”指单个 16 位的 Unicode BMP
代码点。在描述 Unicode 模式行为的上下文中,“字符”指一个 UTF-16 编码的代码点 (6.1.4 )。在任何上下文中,“字符值”指相应非编码代码点的数值。
Pattern 的语法和语义被定义为,如果
Pattern 的源文本是一个
列表 的 SourceCharacter
值,其中每个 SourceCharacter 对应一个 Unicode 代码点。如果一个
BMP 模式包含一个非 BMP SourceCharacter ,则整个模式使用 UTF-16
编码,并且该编码的各个代码单元作为 列表 的元素。
注
例如,考虑一个源文本表示为单个非 BMP 字符 U+1D11E(音乐符号 G 谱号)的模式。解释为 Unicode 模式时,它将是一个单元素(字符) 列表 ,由单个代码点
U+1D11E 组成。然而,解释为 BMP 模式时,它首先使用 UTF-16 编码生成一个两元素 列表 ,由代码单元
0xD834 和 0xDD1E 组成。
模式作为 ECMAScript 字符串值传递给 RegExp 构造函数 ,其中非 BMP 字符使用 UTF-16 编码。例如,单个字符音乐符号
G 谱号模式,表示为一个字符串值,是一个长度为 2
的字符串 ,其元素为代码单元 0xD834 和 0xDD1E。因此,无需进一步转换字符串即可将其处理为由两个模式字符组成的 BMP 模式。然而,要将其处理为 Unicode
模式,需要使用 UTF16SurrogatePairToCodePoint
生成一个 列表 ,其唯一元素是单个模式字符,即代码点
U+1D11E。
实现实际上可能不会执行这样的 UTF-16 翻译,但本规范的语义要求模式匹配的结果好像进行了这样的翻译。
22.2.2.1 符号
下面的描述使用以下内部数据结构:
22.2.2.1.1 RegExp 记录
RegExp 记录 是一个 记录
值,用于存储在编译期间和可能在匹配期间需要的 RegExp 信息。
它具有以下字段:
表 66:RegExp 记录 字段
字段名称
值
含义
[[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 记录 )并返回一个接受字符列表和非负整数的
抽象闭包 ,并返回一个 匹配结果 。它根据以下规则分段定义:
Pattern
::
Disjunction
1. 令 m 为 CompileSubpattern 的 Disjunction ,参数为
rer 和 forward 。
2. 返回一个带有参数(Input , index )的新 抽象闭包 ,捕获 rer 和
m 并在调用时执行以下步骤:
a. 断言 :Input 是一个字符的 列表 。
b. 断言 :0 ≤ index ≤
Input 中元素的数量。
c. 令 c 为一个新的 MatcherContinuation ,带有参数(y ),不捕获任何内容并在调用时执行以下步骤:
i. 断言 :y 是一个 MatchState 。
ii. 返回 y 。
d. 令 cap 为一个 rer .[[CapturingGroupsCount]] 个 undefined 值的 列表 ,索引从
1 到 rer .[[CapturingGroupsCount]] 。
e. 令 x 为 MatchState
{ [[Input]] : Input , [[EndIndex]] :
index , [[Captures]] : cap }。
f. 返回 m (x , c )。
注
一个模式编译为一个 抽象闭包 值。RegExpBuiltinExec
然后可以将此过程应用于一个字符的 列表 和该
列表
中的一个偏移量,以确定模式是否会从该 列表
中正好从该偏移量开始匹配,如果匹配,则捕获括号的值是什么。22.2.2 中的算法设计为,编译模式可能会抛出
SyntaxError 异常;另一方面,一旦模式成功编译,将结果 抽象闭包
应用于一个字符的 列表
以找到匹配项不能抛出异常(除任何 实现定义 的异常,如内存不足,可以在任何地方发生)。
22.2.2.3 运行时语义:CompileSubpattern
语法导向操作
CompileSubpattern 接受参数 rer (一个
RegExp 记录
)和direction (forward 或 backward ),并返回一个
Matcher
。
注 1
它根据以下规则分段定义:
Disjunction
::
Alternative
|
Disjunction
1. 令 m1 为
CompileSubpattern
的
Alternative
,参数为 rer 和 direction 。
2. 令 m2 为
CompileSubpattern
的
Disjunction
,参数为 rer 和 direction 。
3. 返回
MatchTwoAlternatives
(m1 , m2 )。
注 2
|
正则表达式运算符分隔两个替代项。模式首先尝试匹配左边的
Alternative
(后跟正则表达式的后续部分);如果失败,则尝试匹配右边的
Disjunction
(后跟正则表达式的后续部分)。如果左边的
Alternative
,右边的
Disjunction
和后续部分都有选择点,则在移动到左边的下一个选择之前,先尝试后续部分中的所有选择。如果左边的
Alternative
中的选择用尽,则右边的
Alternative
中的选择用尽,则尝试右边的
Disjunction
而不是左边的
Alternative
。以此类推,任何包含在 |
跳过部分中的捕获括号都会生成
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
::
[空]
1. 返回
EmptyMatcher
()。
Alternative
::
Alternative
Term
1. 令 m1 为
CompileSubpattern
的
Alternative
,参数为 rer 和 direction 。
2. 令 m2 为
CompileSubpattern
的
Term
,参数为 rer 和 direction 。
3. 返回
MatchSequence
(m1 , m2 , direction )。
注 3
连续的
Term
尝试同时匹配Input 的连续部分。当direction 为
forward
时,如果左边的
Alternative
,右边的
Term
和正则表达式的后续部分都有选择点,则在移动到右边的下一个选择之前,先尝试后续部分中的所有选择,而在移动到左边的下一个选择之前,先尝试右边
Term
中的所有选择。当direction 为backward 时,
Alternative
和
Term
的求值顺序将被颠倒。
Term
::
Assertion
1. 返回
CompileAssertion
的
Assertion
,参数为 rer 。
注 4
生成的
Matcher
与direction 无关。
Term
::
Atom
1. 返回
CompileAtom
的
Atom
,参数为 rer 和 direction 。
Term
::
Atom
Quantifier
1. 令 m 为
CompileAtom
的
Atom
,参数为 rer 和 direction 。
2. 令 q 为
CompileQuantifier
的
Quantifier
。
3.
断言
: q .[[Min]] ≤ q .[[Max]] 。
4. 令 parenIndex 为
CountLeftCapturingParensBefore
(
Term
)。
5. 令 parenCount 为
CountLeftCapturingParensWithin
(
Atom
)。
6. 返回一个新的
Matcher
,其参数为 (x , c ),捕获 m 、q 、parenIndex 和
parenCount ,并在被调用时执行以下步骤:
a.
断言
:x 是一个
MatchState
。
b.
断言
:c 是一个
MatcherContinuation
。
c. 返回
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 (一个非负的
整数
),并返回一个
MatchResult
。它在被调用时执行以下步骤:
1. 如果 max = 0,返回 c (x )。
2. 令 d 为一个新的
MatcherContinuation
,其参数为 (y ),捕获
m 、min 、max 、greedy 、x 、c 、parenIndex
和 parenCount ,并在被调用时执行以下步骤:
a.
断言
:y 是一个
MatchState
。
b. 如果 min = 0 且 y .[[EndIndex]] = x .[[EndIndex]] ,返回
failure 。
c. 如果 min = 0,令 min2 为 0;否则令
min2
为 min - 1。
d. 如果 max = +∞,令 max2 为 +∞;否则令
max2 为 max - 1。
e. 返回
RepeatMatcher
(m , min2 , max2 , greedy , y ,
c 、parenIndex 、parenCount )。
3. 令 cap 为 x .[[Captures]] 的副本。
4. 对于
整数
k 在
包含区间
从 parenIndex + 1 到 parenIndex + parenCount ,设置
cap [k ] 为 undefined 。
5. 令 Input 为 x .[[Input]] 。
6. 令 e 为 x .[[EndIndex]] 。
7. 令 xr 为
x .[[Input]] :Input ,x .[[EndIndex]] :e ,x .[[Captures]] :cap 的
MatchState
。
8. 如果 min ≠ 0,返回
m (xr ,d )。
9. 如果 greedy 是 false ,则
a. 令 z 为 c (x )。
b. 如果 z 不是 failure ,则返回
z 。
c. 返回 m (xr ,d )。
10. 令 z 为 m (xr ,d )。
11. 如果 z 不是 failure ,则返回
z 。
12. 返回 c (x )。
注 1
一个
Atom
后跟一个
Quantifier
被重复
Quantifier
指定的次数。
Quantifier
可以是非贪婪的,在这种情况下,
Atom
模式被尽可能少的重复,同时仍然匹配后续部分;或者它可以是贪婪的,在这种情况下,
Atom
模式被尽可能多的重复,同时仍然匹配后续部分。
Atom
模式被重复,而不是它匹配的输入字符序列,因此
Atom
的不同重复可以匹配不同的输入子字符串。
注 2
如果
Atom
和正则表达式的后续部分都有选择点,
Atom
首先匹配尽可能多的(或尽可能少的,如果是非贪婪的)次数。在移动到
Atom
的最后一次重复的下一个选择之前,先尝试后续部分中的所有选择。在移动到
Atom
的倒数第二次(第 n-1 次)重复的下一个选择之前,先尝试
Atom
的最后一次(第 n 次)重复中的所有选择;这时可能会发现现在可以进行更多或更少的重复;这些会被用尽(再次,从尽可能少或尽可能多的重复开始),然后再移动到倒数第二次(第 n-1
次)重复的下一个选择,依此类推。
比较
/a[a-z]{2,4}/.exec ("abcdefghi" )
返回 "abcde" 与
/a[a-z]{2,4}?/.exec ("abcdefghi" )
返回 "abc" 。
考虑还包括
/(aa|aabaac|ba|b|c)*/.exec ("aabaac" )
按上述选择点顺序返回数组
["aaba" , "ba" ]
而不是以下任一项:
["aabaac" , "aabaac" ]
["aabaac" , "c" ]
上述选择点顺序可用于编写一个正则表达式来计算两个数字的最大公约数(以一进制表示)。以下示例计算 10 和 15 的 gcd:
"aaaaaaaaaa,aaaaaaaaaaaaaaa" .replace (/^(a+)\1*,\1+$/ , "$1" )
以一进制表示返回 gcd"aaaaa" 。
注 3
RepeatMatcher 的步骤
4
在每次重复
Atom
时清除它的捕获。我们可以在正则表达式
/(z)((a+)?(b+)?(c))*/.exec ("zaacbbbcac" )
中看到其行为,它返回数组
["zaacbbbcac" , "z" , "ac" , "a" , undefined , "c" ]
而不是
["zaacbbbcac" , "z" , "ac" , "a" , "bbb" , "c" ]
因为最外层的*
的每次迭代都会清除所有包含在量化
Atom
中的捕获字符串,在这种情况下包括编号为 2、3、4 和 5 的捕获字符串。
注 4
RepeatMatcher 的步骤
2.b
规定一旦满足最小重复次数,任何更多的匹配空字符序列的扩展都不会被考虑进一步重复。这可以防止正则表达式引擎在模式上陷入无限循环,例如:
/(a*)*/.exec ("b" )
或者稍微复杂一点:
/(a*)b1+/.exec ("baaaac" )
返回数组
["b" , "" ]
22.2.2.3.2 EmptyMatcher ( )
抽象操作 EmptyMatcher 不接受任何参数,并返回一个 Matcher 。调用时执行以下步骤:
1. 返回一个新的 Matcher ,其参数为 (x ,
c ),不捕获任何内容,调用时执行以下步骤:
a. 断言 :x 是一个 MatchState 。
b. 断言 :c 是一个 MatcherContinuation 。
c. 返回 c (x )。
22.2.2.3.3 MatchTwoAlternatives ( m1 , m2 )
抽象操作 MatchTwoAlternatives 接受参数 m1 (一个 Matcher )和 m2 (一个 Matcher ),并返回一个 Matcher 。调用时执行以下步骤:
1. 返回一个新的 Matcher ,其参数为 (x ,
c ),捕获 m1 和 m2 ,调用时执行以下步骤:
a. 断言 :x 是一个 MatchState 。
b. 断言 :c 是一个 MatcherContinuation 。
c. 令 r 为 m1 (x , c )。
d. 如果 r 不是 failure ,返回
r 。
e. 返回 m2 (x , c )。
22.2.2.3.4 MatchSequence ( m1 , m2 ,
direction )
抽象操作 MatchSequence 接受参数 m1 (一个 Matcher )、m2 (一个 Matcher )和
direction (forward 或 backward ),并返回一个 Matcher 。调用时执行以下步骤:
1. 如果 direction 是 forward ,则
a. 返回一个新的 Matcher ,其参数为 (x ,
c ),捕获 m1 和 m2 ,调用时执行以下步骤:
i. 断言 :x 是一个 MatchState 。
ii. 断言 :c 是一个 MatcherContinuation 。
iii. 令 d 为一个新的 MatcherContinuation ,其参数为
(y ),捕获 c 和 m2 ,调用时执行以下步骤:
1. 断言 :y 是一个 MatchState 。
2. 返回 m2 (y , c )。
iv. 返回 m1 (x , d )。
2. 否则,
a. 断言 :direction 是
backward 。
b. 返回一个新的 Matcher ,其参数为 (x ,
c ),捕获 m1 和 m2 ,调用时执行以下步骤:
i. 断言 :x 是一个 MatchState 。
ii. 断言 :c 是一个 MatcherContinuation 。
iii. 令 d 为一个新的 MatcherContinuation ,其参数为
(y ),捕获 c 和 m1 ,调用时执行以下步骤:
1. 断言 :y 是一个 MatchState 。
2. 返回 m1 (y , c )。
iv. 返回 m2 (x , d )。
22.2.2.4 运行时语义:CompileAssertion
语法定向操作 CompileAssertion 接受参数 rer (一个
正则表达式记录 ),并返回一个
匹配器 。
注 1
它按以下产生式逐段定义:
Assertion
::
^
1. 返回一个新的
匹配器 ,其参数为 (x ,
c ),捕获 rer 并在调用时执行以下步骤:
a. 断言:x 是一个 匹配状态 。
b. 断言:c 是一个 匹配器延续 。
c. 令 Input 为 x .[[Input]] 。
d. 令 e 为 x .[[EndIndex]] 。
e. 如果 e = 0,或者如果 rer .[[Multiline]] 为 true 且字符 Input [e -
1]
被
行终止符
匹配,则
i. 返回 c (x )。
f. 返回 failure 。
注 2
即使使用 y
标志,^
也只匹配 Input 的开头,或者(如果 rer .[[Multiline]] 为 true )行的开头。
Assertion
::
$
1. 返回一个新的
匹配器 ,其参数为 (x ,
c ),捕获 rer 并在调用时执行以下步骤:
a. 断言:x 是一个 匹配状态 。
b. 断言:c 是一个 匹配器延续 。
c. 令 Input 为 x .[[Input]] 。
d. 令 e 为 x .[[EndIndex]] 。
e. 令 InputLength 为 Input 中的元素数量。
f. 如果 e = InputLength ,或者如果
rer .[[Multiline]] 为 true 且字符
Input [e ] 被
行终止符
匹配,则
i. 返回 c (x )。
g. 返回 failure 。
Assertion
::
\b
1. 返回一个新的
匹配器 ,其参数为 (x ,
c ),捕获 rer 并在调用时执行以下步骤:
a. 断言:x 是一个 匹配状态 。
b. 断言:c 是一个 匹配器延续 。
c. 令 Input 为 x .[[Input]] 。
d. 令 e 为 x .[[EndIndex]] 。
e. 令 a 为 IsWordChar (rer ,
Input , e - 1)。
f. 令 b 为 IsWordChar (rer ,
Input , e )。
g. 如果 a 为 true 且 b 为
false ,或者 a 为 false 且 b 为
true ,则返回 c (x )。
h. 返回 failure 。
Assertion
::
\B
1. 返回一个新的
匹配器 ,其参数为 (x ,
c ),捕获 rer 并在调用时执行以下步骤:
a. 断言:x 是一个 匹配状态 。
b. 断言:c 是一个 匹配器延续 。
c. 令 Input 为 x .[[Input]] 。
d. 令 e 为 x .[[EndIndex]] 。
e. 令 a 为 IsWordChar (rer ,
Input , e - 1)。
f. 令 b 为 IsWordChar (rer ,
Input , e )。
g. 如果 a 为 true 且 b 为
true ,或者 a 为 false 且 b 为
false ,则返回 c (x )。
h. 返回 failure 。
Assertion
::
(?=
Disjunction
)
1. 令 m 为 CompileSubpattern 的结果,参数为
rer 和 forward 。
2. 返回一个新的
匹配器 ,其参数为 (x ,
c ),捕获 m 并在调用时执行以下步骤:
a. 断言:x 是一个 匹配状态 。
b. 断言:c 是一个 匹配器延续 。
c. 令 d 为一个新的 匹配器延续 ,参数为
(y ),捕获为空,在调用时执行以下步骤:
i. 断言:y 是一个 匹配状态 。
ii. 返回 y 。
d. 令 r 为 m (x , d )。
e. 如果 r 为 failure ,返回
failure 。
f. 断言:r 是一个 匹配状态 。
g. 令 cap 为 r .[[Captures]] 。
h. 令 Input 为 x .[[Input]] 。
i. 令 xe 为 x .[[EndIndex]] 。
j. 令 z 为匹配状态 { [[Input]] :
Input , [[EndIndex]] : xe , [[Captures]] : cap }。
k. 返回 c (z )。
注 3
形式 (?=
Disjunction )
指定零宽正前瞻。为了成功,Disjunction
内的模式必须在当前位置匹配,但在匹配后续之前当前位置不会前移。如果
Disjunction
可以在当前位置以多种方式匹配,则只尝试第一种。与其他正则表达式运算符不同,不会回溯到 (?=
形式(这种不寻常的行为继承自 Perl)。这仅在
Disjunction
包含捕获括号且模式的后续部分包含对这些捕获的反向引用时才重要。
例如,
/(?=(a+))/.exec ("baaabac" )
在第一个 b
后立即匹配空字符串,因此返回数组:
["" , "aaa" ]
为了说明缺少回溯到前瞻,考虑:
/(?=(a+))a*b\1 /.exec ("baaabac" )
此表达式返回
["aba" , "a" ]
而不是:
["aaaba" , "a" ]
Assertion
::
(?!
Disjunction
)
1. 令 m 为 CompileSubpattern 的结果,参数为
rer 和 forward 。
2. 返回一个新的
匹配器 ,其参数为 (x ,
c ),捕获 m 并在调用时执行以下步骤:
a. 断言:x 是一个 匹配状态 。
b. 断言:c 是一个 匹配器延续 。
c. 令 d 为一个新的 匹配器延续 ,参数为
(y ),捕获为空,在调用时执行以下步骤:
i. 断言:y 是一个 匹配状态 。
ii. 返回 y 。
d. 令 r 为 m (x , d )。
e. 如果 r 不是 failure ,返回
failure 。
f. 返回 c (x )。
注 4
形式 (?!
Disjunction )
指定零宽负前瞻。为了成功,Disjunction
内的模式必须在当前位置失败。当前位置不会在匹配后续之前前移。
Disjunction
可以包含捕获括号,但对它们的反向引用仅在 Disjunction
内有意义。来自模式其他地方的这些捕获括号的反向引用总是返回 undefined ,因为负前瞻必须失败才能使模式成功。例如,
/(.*?)a (?!(a+)b\2c)\2 (.*)/.exec ("baaabaac" )
查找不紧跟某个正数 a
的 a
,b
,另一个 n
a
(由第一个
\2
指定)和一个 c
。第二个 \2
在负前瞻之外,因此匹配 undefined
并且总是成功。整个表达式返回数组:
["baaabaac" , "ba" , undefined , "abaac" ]
Assertion
::
(?<=
Disjunction
)
1. 令 m 为 CompileSubpattern 的结果,参数为
rer 和 backward 。
2. 返回一个新的
匹配器 ,其参数为 (x ,
c ),捕获 m 并在调用时执行以下步骤:
a. 断言:x 是一个 匹配状态 。
b. 断言:c 是一个 匹配器延续 。
c. 令 d 为一个新的 匹配器延续 ,参数为
(y ),捕获为空,在调用时执行以下步骤:
i. 断言:y 是一个 匹配状态 。
ii. 返回 y 。
d. 令 r 为 m (x , d )。
e. 如果 r 为 failure ,返回
failure 。
f. 断言:r 是一个 匹配状态 。
g. 令 cap 为 r .[[Captures]] 。
h. 令 Input 为 x .[[Input]] 。
i. 令 xe 为 x .[[EndIndex]] 。
j. 令 z 为匹配状态 { [[Input]] :
Input , [[EndIndex]] : xe , [[Captures]] : cap }。
k. 返回 c (z )。
Assertion
::
(?<!
Disjunction
)
1. 令 m 为 CompileSubpattern 的结果,参数为
rer 和 backward 。
2. 返回一个新的
匹配器 ,其参数为 (x ,
c ),捕获 m 并在调用时执行以下步骤:
a. 断言:x 是一个 匹配状态 。
b. 断言:c 是一个 匹配器延续 。
c. 令 d 为一个新的 匹配器延续 ,参数为
(y ),捕获为空,在调用时执行以下步骤:
i. 断言:y 是一个 匹配状态 。
ii. 返回 y 。
d. 令 r 为 m (x , d )。
e. 如果 r 不是 failure ,返回
failure 。
f. 返回 c (x )。
22.2.2.4.1 IsWordChar ( rer , Input , e )
抽象操作 IsWordChar 接受参数 rer (一个
正则表达式记录 ),Input (一个字符的
列表 ),和
e (一个
整数 ),并返回一个布尔值。在调用时执行以下步骤:
1. 令 InputLength 为 Input 中的元素数量。
2. 如果 e = -1 或 e = InputLength ,返回
false 。
3. 令 c 为字符 Input [e ]。
4. 如果 WordCharacters (rer )
包含 c ,返回 true 。
5. 返回 false 。
22.2.2.5 运行时语义:CompileQuantifier
语法导向操作 CompileQuantifier
不接受参数,并返回一个包含字段 [[Min]] (一个非负 整数 )、[[Max]] (一个非负
整数 或
+∞)和 [[Greedy]] (一个布尔值)的 记录 。
它按以下产生式逐段定义:
Quantifier
::
QuantifierPrefix
1. 令 qp 为 CompileQuantifierPrefix
的结果,参数为 QuantifierPrefix 。
2. 返回记录 { [[Min]] : qp .[[Min]] , [[Max]] : qp .[[Max]] , [[Greedy]] : true }。
Quantifier
::
QuantifierPrefix
?
1. 令 qp 为 CompileQuantifierPrefix
的结果,参数为 QuantifierPrefix 。
2. 返回记录 { [[Min]] : qp .[[Min]] , [[Max]] : qp .[[Max]] , [[Greedy]] : false }。
22.2.2.6 运行时语义:CompileQuantifierPrefix
语法导向操作 CompileQuantifierPrefix
不接受参数,并返回一个包含字段 [[Min]] (一个非负 整数 )和 [[Max]] (一个非负
整数 或
+∞)的 记录 。它按以下产生式逐段定义:
QuantifierPrefix
::
*
1. 返回记录 { [[Min]] : 0, [[Max]] : +∞ }。
QuantifierPrefix
::
+
1. 返回记录 { [[Min]] : 1, [[Max]] : +∞ }。
QuantifierPrefix
::
?
1. 返回记录 { [[Min]] : 0, [[Max]] : 1 }。
QuantifierPrefix
::
{
DecimalDigits
}
1. 令 i 为 DecimalDigits 的 MV(见 12.9.3 )。
2. 返回记录 { [[Min]] : i , [[Max]] : i }。
QuantifierPrefix
::
{
DecimalDigits
,}
1. 令 i 为 DecimalDigits 的 MV。
2. 返回记录 { [[Min]] : i , [[Max]] : +∞ }。
QuantifierPrefix
::
{
DecimalDigits
,
DecimalDigits
}
1. 令 i 为第一个 DecimalDigits 的 MV。
2. 令 j 为第二个 DecimalDigits 的 MV。
3. 返回记录 { [[Min]] : i , [[Max]] : j }。
22.2.2.7 运行时语义:CompileAtom
语法导向操作 CompileAtom
接受参数 rer (一个 RegExp 记录 )和
direction (forward 或 backward ),并返回一个 Matcher 。
注 1
它通过以下产生式逐段定义:
Atom ::
PatternCharacter
1. 令 ch 为 PatternCharacter 匹配的字符。
2. 令 A 为一个包含字符 ch 的单元素 CharSet 。
3. 返回 CharacterSetMatcher (rer ,
A , false , direction )。
Atom ::
.
1. 令 A 为 AllCharacters (rer )。
2. 如果 rer .[[DotAll]] 不是
true ,则
a. 从 A 中移除所有对应于 LineTerminator 产生式右侧的代码点的字符。
3. 返回 CharacterSetMatcher (rer ,
A , false , direction )。
Atom ::
CharacterClass
1. 令 cc 为 CompileCharacterClass ,使用参数
rer 和 CharacterClass 。
2. 令 cs 为 cc .[[CharSet]] 。
3. 如果 rer .[[UnicodeSets]] 是
false ,或者 cs 的每个 CharSetElement 都由单个字符组成(包括
cs 为空的情况),则返回 CharacterSetMatcher (rer ,
cs , cc .[[Invert]] , direction )。
4. 断言 : cc .[[Invert]] 是 false 。
5. 令 lm 为一个空的 列表 ,其中包含
Matchers 。
6. 对于 cs 中每个包含多个字符的 CharSetElement
s ,按长度递减顺序迭代,执行以下操作:
a. 令 cs2 为一个包含 s 的最后一个代码点的单元素 CharSet 。
b. 令 m2 为 CharacterSetMatcher (rer ,
cs2 , false , direction )。
c. 对于 s 中的每个代码点 c1 ,从倒数第二个代码点开始向后迭代,执行以下操作:
i. 令 cs1 为一个包含 c1 的单元素 CharSet 。
ii. 令 m1 为 CharacterSetMatcher (rer ,
cs1 , false , direction )。
iii. 将 m2 设置为 MatchSequence (m1 ,
m2 , direction )。
d. 将 m2 附加到 lm 。
7. 令 singles 为包含 cs 中每个由单个字符组成的 CharSet 。
8. 将 CharacterSetMatcher (rer ,
singles , false , direction ) 附加到 lm 。
9. 如果 cs 包含空字符序列,将 EmptyMatcher ()
附加到
lm 。
10. 令 m2 为 lm 中的最后一个 Matcher 。
11. 对于 lm 中的每个 Matcher
m1 ,从倒数第二个元素开始向后迭代,执行以下操作:
a. 将 m2 设置为 MatchTwoAlternatives (m1 ,
m2 )。
12. 返回 m2 。
Atom ::
(
GroupSpecifier opt
Disjunction
)
1. 令 m 为 CompileSubpattern 的 Disjunction ,使用参数
rer 和 direction 。
2. 令 parenIndex 为 CountLeftCapturingParensBefore (Atom )。
3. 返回一个新的 Matcher ,其参数为 (x ,
c ),并捕获 direction 、m 和 parenIndex ,并在调用时执行以下步骤:
a. 断言 : x 是 MatchState 。
b. 断言 : c 是 MatcherContinuation 。
c. 令 d 为一个新的 MatcherContinuation ,其参数为
(y ),并捕获 x 、c 、direction 和
parenIndex ,并在调用时执行以下步骤:
i. 断言 : y 是 MatchState 。
ii. 令 cap 为 y .[[Captures]] 的副本。
iii. 令 Input 为 x .[[Input]] 。
iv. 令 xe 为 x .[[EndIndex]] 。
v. 令 ye 为 y .[[EndIndex]] 。
vi. 如果 direction 是
forward ,则
1. 断言 : xe ≤
ye 。
2. 令 r 为 CaptureRange {
[[StartIndex]] : xe , [[EndIndex]] :
ye }。
vii. 否则,
1. 断言 : direction 是
backward 。
2. 断言 : ye ≤
xe 。
3. 令 r 为 CaptureRange {
[[StartIndex]] : ye , [[EndIndex]] :
xe }。
viii. 将 cap [parenIndex + 1] 设置为
r 。
ix. 令 z 为 MatchState { [[Input]] : Input , [[EndIndex]] :
ye , [[Captures]] : cap }。
x. 返回 c (z )。
d. 返回 m (x , d )。
注 2
形式为 (
Disjunction )
的括号既用于将
Disjunction
模式的组件组合在一起,也用于保存匹配的结果。该结果可以在反向引用(\
后跟一个非零十进制数)、替换字符串中引用或作为数组的一部分从正则表达式匹配的 抽象闭包 返回。要抑制括号的捕获行为,请使用形式
(?:
Disjunction )
代替。
Atom ::
(?: Disjunction )
1. 返回 CompileSubpattern 的 Disjunction ,使用参数
rer 和 direction 。
AtomEscape
::
DecimalEscape
1. 令 n 为 CapturingGroupNumber
的 DecimalEscape 。
2. 断言 : n ≤ rer .[[CapturingGroupsCount]] 。
3. 返回 BackreferenceMatcher (rer ,
n , direction )。
注 3
形式为 \
后跟非零十进制数 n 的转义序列匹配第 n 组捕获括号的结果(22.2.2.1 )。如果正则表达式的捕获括号少于
n ,则这是一个错误。如果正则表达式有 n 或更多的捕获括号,但第 n 个捕获括号是
undefined ,因为它没有捕获任何内容,则反向引用总是成功。
AtomEscape
::
CharacterEscape
1. 令 cv 为 CharacterValue
的 CharacterEscape 。
2. 令 ch 为字符值为 cv 的字符。
3. 令 A 为一个包含字符 ch 的单元素 CharSet 。
4. 返回 CharacterSetMatcher (rer ,
A , false , direction )。
AtomEscape
::
CharacterClassEscape
1. 令 cs 为 CompileToCharSet 的 CharacterClassEscape ,使用参数
rer 。
2. 如果 rer .[[UnicodeSets]] 是
false ,或者 cs 的每个 CharSetElement 都由单个字符组成(包括
cs 为空的情况),则返回 CharacterSetMatcher (rer ,
cs , false , direction )。
3. 令 lm 为一个空的 列表 ,其中包含
Matchers 。
4. 对于 cs 中每个包含多个字符的 CharSetElement
s ,按长度递减顺序迭代,执行以下操作:
a. 令 cs2 为一个包含 s 的最后一个代码点的单元素 CharSet 。
b. 令 m2 为 CharacterSetMatcher (rer ,
cs2 , false , direction )。
c. 对于 s 中的每个代码点 c1 ,从倒数第二个代码点开始向后迭代,执行以下操作:
i. 令 cs1 为一个包含 c1 的单元素 CharSet 。
ii. 令 m1 为 CharacterSetMatcher (rer ,
cs1 , false , direction )。
iii. 将 m2 设置为 MatchSequence (m1 ,
m2 , direction )。
d. 将 m2 附加到 lm 。
5. 令 singles 为包含 cs 中每个由单个字符组成的 CharSet 。
6. 将 CharacterSetMatcher (rer ,
singles , false , direction ) 附加到 lm 。
7. 如果 cs 包含空字符序列,将 EmptyMatcher ()
附加到
lm 。
8. 令 m2 为 lm 中的最后一个 Matcher 。
9. 对于 lm 中的每个 Matcher
m1 ,从倒数第二个元素开始向后迭代,执行以下操作:
a. 将 m2 设置为 MatchTwoAlternatives (m1 ,
m2 )。
10. 返回 m2 。
AtomEscape
::
k
GroupName
1. 令 matchingGroupSpecifiers 为 GroupSpecifiersThatMatch (GroupName )。
2. 断言 :matchingGroupSpecifiers 包含单个
GroupSpecifier 。
3. 令 groupSpecifier 为 matchingGroupSpecifiers
的唯一元素。
4. 令 parenIndex 为 CountLeftCapturingParensBefore (groupSpecifier )。
5. 返回 BackreferenceMatcher (rer ,
parenIndex , direction )。
22.2.2.7.1 字符集匹配器 (CharacterSetMatcher) ( rer , A ,
invert , direction )
抽象操作字符集匹配器接受参数 rer (一个 正则表达式记录 ), A (一个
字符集 ), invert (一个布尔值), 和
direction (forward 或 backward ), 并返回一个 匹配器 . 调用时执行以下步骤:
1. 如果 rer .[[UnicodeSets]] 是
true , 那么
a. 断言 : invert 是
false .
b. 断言 : A 中的每个 字符集元素 由单个字符组成.
2. 返回一个新的 匹配器 ,参数为 (x ,
c ), 捕获 rer , A , invert 和 direction ,
并在调用时执行以下步骤:
a. 断言 : x 是一个 匹配状态 .
b. 断言 : c 是一个 匹配器延续 .
c. 令 Input 为 x .[[Input]] .
d. 令 e 为 x .[[EndIndex]] .
e. 如果 direction 是 forward , 令
f 为 e + 1.
f. 否则,令 f 为 e - 1.
g. 令 InputLength 为 Input 中元素的数量.
h. 如果 f
< 0 或 f > InputLength , 返回 failure .
i. 令 index 为 min (e ,
f ).
j. 令 ch 为 Input [index ].
k. 令 cc 为 Canonicalize (rer ,
ch ).
l. 如果存在一个 字符集元素
在
A 中, 其仅包含一个字符 a ,并且 Canonicalize (rer ,
a ) 是 cc ,令 found 为 true . 否则, 令
found
为 false .
m. 如果 invert 是 false 并且
found 是 false , 返回 failure .
n. 如果 invert 是 true 并且
found 是 true , 返回 failure .
o. 令 cap 为 x .[[Captures]] .
p. 令 y 为 匹配状态 {
[[Input]] : Input , [[EndIndex]] :
f , [[Captures]] : cap }.
q. 返回 c (y ).
22.2.2.7.2 BackreferenceMatcher ( rer , n ,
direction )
抽象操作 BackreferenceMatcher 接受参数 rer (一个 正则表达式记录 ),
n
(一个正整数 integer ), 和 direction
(forward 或 backward ),并返回一个 匹配器 。调用时执行以下步骤:
1. 断言 : n ≥ 1。
2. 返回一个新的 匹配器
,参数为 (x , c ),捕获 rer , n 和
direction ,并在调用时执行以下步骤:
a. 断言 : x 是一个 匹配状态 。
b. 断言 : c 是一个 匹配器延续 。
c. 令 Input 为 x .[[Input]] 。
d. 令 cap 为 x .[[Captures]] 。
e. 令 r 为 cap [n ]。
f. 如果 r 是 undefined ,返回
c (x )。
g. 令 e 为 x .[[EndIndex]] 。
h. 令 rs 为 r .[[StartIndex]] 。
i. 令 re 为 r .[[EndIndex]] 。
j. 令 len 为 re - rs 。
k. 如果 direction 是 forward ,令
f 为 e + len 。
l. 否则,令 f 为 e - len 。
m. 令 InputLength 为 Input 中元素的数量。
n. 如果 f
< 0 或 f > InputLength ,返回 failure 。
o. 令 g 为 min (e , f )。
p. 如果存在一个 整数 i 在从 0(包括)到
len (不包括)的 区间 中,使得 Canonicalize (rer ,
Input [rs + i ]) 不等于 Canonicalize (rer ,
Input [g + i ]),返回 failure 。
q. 令 y 为 匹配状态 {
[[Input]] : Input , [[EndIndex]] :
f , [[Captures]] : cap }。
r. 返回 c (y )。
22.2.2.7.3 Canonicalize ( rer , ch )
抽象操作 Canonicalize 接受参数 rer (一个 正则表达式记录 ) 和 ch (一个字符)
并返回一个字符。调用时执行以下步骤:
1. 如果 HasEitherUnicodeFlag (rer )
是 true 且 rer .[[IgnoreCase]] 是
true ,则
a. 如果 Unicode 字符数据库的 CaseFolding.txt
文件为 ch 提供了一个简单或常见的大小写折叠映射,返回应用该映射到 ch 的结果。
b. 返回 ch 。
2. 如果 rer .[[IgnoreCase]] 是
false ,返回 ch 。
3. 断言 : ch 是一个 UTF-16 代码单元。
4. 令 cp 为数值等于 ch 数值的代码点。
5. 令 u 为根据 Unicode 默认大小写转换算法,将 cp 转换为大写的结果。
6. 令 uStr 为 CodePointsToString (u )。
7. 如果 uStr 的长度 ≠ 1,返回 ch 。
8. 令 cu 为 uStr 的唯一代码单元元素。
9. 如果 ch 的数值 ≥ 128 且 cu 的数值 < 128,返回
ch 。
10. 返回 cu 。
注
在大小写不敏感的匹配中,当 HasEitherUnicodeFlag (rer )
为 true 时,所有字符在比较之前都会隐式地使用 Unicode 标准提供的简单映射进行大小写折叠。简单映射总是映射到单个代码点,因此不会将
ß
(U+00DF 德语小写字母尖S) 映射为 ss
或
SS
。然而,它可能会将基本拉丁语块之外的代码点映射到其中的代码点,例如,ſ
(U+017F 拉丁小写长S) 会大小写折叠为
s
(U+0073 拉丁小写字母S),K
(U+212A 开尔文符号) 会大小写折叠为 k
(U+006B
拉丁小写字母K)。包含这些代码点的字符串可以被正则表达式如 /[a-z]/ui
匹配。
在大小写不敏感的匹配中,当 HasEitherUnicodeFlag (rer )
为 false 时,映射基于 Unicode 默认大小写转换算法 toUppercase 而非
toCasefold,导致一些微妙的差异。例如,Ω
(U+2126 欧姆符号) 被 toUppercase 映射为其本身,但被 toCasefold 映射为
ω
(U+03C9 希腊小写字母欧米茄) 和 Ω
(U+03A9 希腊大写字母欧米茄),因此 "\u2126"
可以被 /[ω]/ui
和 /[\u03A9]/ui
匹配,但不能被 /[ω]/i
或
/[\u03A9]/i
匹配。此外,没有代码点会从基本拉丁语块外映射到其中的代码点,因此像 "\u017F ſ" 和
"\u212A K" 这样的字符串不会被 /[a-z]/i
匹配。
22.2.2.8 运行时语义:CompileCharacterClass
语法定向操作
CompileCharacterClass 接受参数 rer (一个 正则表达式记录 ) 并返回一个包含字段 [[CharSet]] (一个 字符集 ) 和 [[Invert]] (一个布尔值) 的 记录 。它按以下生成式逐段定义:
CharacterClass
::
[
ClassContents
]
1. 让 A 为 CompileToCharSet 对 ClassContents
以参数
rer 调用的结果。
2. 返回 记录 { [[CharSet]] : A , [[Invert]] :
false }。
CharacterClass
::
[^
ClassContents
]
1. 让 A 为 CompileToCharSet 对 ClassContents
以参数
rer 调用的结果。
2. 如果 rer .[[UnicodeSets]] 是
true ,则
a. 返回 记录 {
[[CharSet]] : CharacterComplement (rer ,
A ), [[Invert]] : false }。
3. 返回 记录 { [[CharSet]] : A , [[Invert]] :
true }。
22.2.2.9 运行时语义:CompileToCharSet
语法定向操作
CompileToCharSet 接受参数 rer (一个 正则表达式记录 ) 并返回一个 字符集 。
注 1
它通过以下生成规则分段定义:
ClassContents
::
[empty]
1. 返回空的 字符集 。
NonemptyClassRanges
::
ClassAtom
NonemptyClassRangesNoDash
1. 令 A 为 CompileToCharSet 计算 ClassAtom ,参数为
rer 。
2. 令 B 为 CompileToCharSet 计算 NonemptyClassRangesNoDash ,参数为
rer 。
3. 返回 字符集 A 和 B
的并集。
NonemptyClassRanges
::
ClassAtom
-
ClassAtom
ClassContents
1. 令 A 为 CompileToCharSet 计算第一个
ClassAtom ,参数为
rer 。
2. 令 B 为 CompileToCharSet 计算第二个
ClassAtom ,参数为
rer 。
3. 令 C 为 CompileToCharSet 计算 ClassContents ,参数为
rer 。
4. 令 D 为 CharacterRange (A ,
B )。
5. 返回 D 和 C 的并集。
NonemptyClassRangesNoDash
::
ClassAtomNoDash
NonemptyClassRangesNoDash
1. 令 A 为 CompileToCharSet 计算 ClassAtomNoDash ,参数为
rer 。
2. 令 B 为 CompileToCharSet 计算 NonemptyClassRangesNoDash ,参数为
rer 。
3. 返回 A 和 B 的并集。
NonemptyClassRangesNoDash
::
ClassAtomNoDash
-
ClassAtom
ClassContents
1. 令 A 为 CompileToCharSet 计算 ClassAtomNoDash ,参数为
rer 。
2. 令 B 为 CompileToCharSet 计算 ClassAtom ,参数为
rer 。
3. 令 C 为 CompileToCharSet 计算 ClassContents ,参数为
rer 。
4. 令 D 为 CharacterRange (A ,
B )。
5. 返回 D 和 C 的并集。
Note 2
ClassContents 可以扩展为一个 ClassAtom
和/或由破折号分隔的两个
ClassAtom
的范围。在后一种情况下,ClassContents 包含第一个 ClassAtom 和第二个
ClassAtom
之间的所有字符(包括这两个字符);如果任何一个 ClassAtom 不表示单个字符(例如,其中一个是
\w),或者如果第一个
ClassAtom
的字符值严格大于第二个 ClassAtom 的字符值,则会发生错误。
Note 3
即使模式忽略大小写,范围两端的大小写在确定哪些字符属于范围时也很重要。因此,例如,模式 /[E-F]/i
仅匹配字母
E
、F
、e
和 f
,而模式 /[E-f]/i
匹配 Unicode
基本拉丁字母块中的所有大写和小写字母,以及符号 [
、\
、]
、^
、_
和
`
。
Note 4
-
字符可以被视为字面意思或表示范围。如果它是 ClassContents
的第一个或最后一个字符,范围指定的开始或结束限制,或紧随范围指定之后,它被视为字面意思。
ClassAtom
:: -
1. 返回包含单个字符 -
U+002D (HYPHEN-MINUS) 的 CharSet 。
ClassAtomNoDash
:: SourceCharacter
but not one of \ or ] or
-
1. 返回包含由 SourceCharacter 匹配的字符的
CharSet 。
ClassEscape
::
b
-
CharacterEscape
1. 令 cv 为此 ClassEscape 的 CharacterValue 。
2. 令 c 为字符值为 cv 的字符。
3. 返回包含单个字符 c 的 CharSet 。
Note 5
一个 ClassAtom
可以使用在整个正则表达式中允许的任何转义序列,除了 \b
、\B
和反向引用。在 CharacterClass 中,\b
表示退格字符,而 \B
和反向引用会引发错误。在 ClassAtom 中使用反向引用会导致错误。
CharacterClassEscape
:: d
1. 返回包含字符
0
、1
、2
、3
、4
、5
、6
、7
、8
和 9
的十元素 CharSet 。
CharacterClassEscape
:: D
1. 让 S 成为由
CharacterClassEscape
:: d
返回的 CharSet 。
2. 返回 CharacterComplement (rer ,
S )。
CharacterClassEscape
:: s
1. 返回 CharSet ,其中包含对应于 WhiteSpace 或
LineTerminator
产生式右侧的所有字符。
CharacterClassEscape
:: S
1. 让 S 成为由
CharacterClassEscape
:: s
返回的 CharSet 。
2. 返回 CharacterComplement (rer ,
S )。
CharacterClassEscape
:: w
1. 返回 MaybeSimpleCaseFolding (rer ,
WordCharacters (rer ))。
CharacterClassEscape
:: W
1. 让 S 成为由
CharacterClassEscape
:: w
返回的 CharSet 。
2. 返回 CharacterComplement (rer ,
S )。
CharacterClassEscape
::
p{
UnicodePropertyValueExpression
}
1. 返回 CompileToCharSet ,其参数为
rer 和 UnicodePropertyValueExpression 。
CharacterClassEscape
::
P{
UnicodePropertyValueExpression
}
1. 令 S 为 CompileToCharSet 的结果,传入参数
UnicodePropertyValueExpression
和 rer 。
2. 断言 :S 仅包含单个代码点。
3. 返回 CharacterComplement (rer ,
S )。
UnicodePropertyValueExpression
::
UnicodePropertyName
=
UnicodePropertyValue
1. 令 ps 为 匹配到的源文本 ,即
UnicodePropertyName 。
2. 令 p 为 UnicodeMatchProperty (rer ,
ps ) 的结果。
3. 断言 :p 是一个 Unicode 属性名称或属性别名,列在
表67
的“属性名称和别名”列中。
4. 令 vs 为 匹配到的源文本 ,即
UnicodePropertyValue 。
5. 令 v 为 UnicodeMatchPropertyValue (p ,
vs ) 的结果。
6. 令 A 为 CharSet ,包含所有在字符数据库定义中包含属性
p 且值为 v 的 Unicode 代码点。
7. 返回 MaybeSimpleCaseFolding (rer ,
A )。
UnicodePropertyValueExpression
::
LoneUnicodePropertyNameOrValue
1.
令 s 为
匹配到的源文本
,
即
LoneUnicodePropertyNameOrValue
。
2.
如果
UnicodeMatchPropertyValue
(General_Category
, s )
是 General_Category (gc) 属性的 Unicode 属性值或属性值别名,列在
PropertyValueAliases.txt
中,则:
a.
返回一个
CharSet
,
其中包含所有在字符数据库定义中包含属性 “General_Category” 且值为 s 的 Unicode 代码点。
3.
令 p 为
UnicodeMatchProperty
(rer , s ) 的结果。
4.
断言
:
p 是一个二元 Unicode 属性或二元属性别名,列在
表68
的“属性名称和别名”列中,或在
表69
中的字符串的二元 Unicode 属性。
5.
令 A 为一个
CharSet
,
其中包含所有字符数据库定义中包含属性 p 且值为 “True” 的 CharSetElements。
6.
返回
MaybeSimpleCaseFolding
(rer , A )。
ClassUnion
::
ClassSetRange
ClassUnion
opt
1. 令 A 为
CompileToCharSet
作用于
ClassSetRange 的结果,其中参数为
rer 。
2. 如果
ClassUnion
存在,则:
a. 令 B 为
CompileToCharSet
作用于
ClassUnion
的结果,其中参数为 rer 。
b. 返回
CharSets
A 和 B 的并集。
3. 返回 A 。
ClassUnion
::
ClassSetOperand
ClassUnion
opt
1. 令 A 为
CompileToCharSet
作用于
ClassSetOperand 的结果,其中参数为
rer 。
2. 如果
ClassUnion
存在,则:
a. 令 B 为
CompileToCharSet
作用于
ClassUnion
的结果,其中参数为 rer 。
b. 返回
CharSets
A 和 B 的并集。
3. 返回 A 。
ClassIntersection
::
ClassSetOperand
&&
ClassSetOperand
1. 令 A 为
CompileToCharSet
作用于
ClassSetOperand 的结果,其中参数为
rer 。
2. 令 B 为
CompileToCharSet
作用于
ClassSetOperand 的结果,其中参数为
rer 。
3. 返回
CharSets
A 和 B 的交集。
ClassIntersection
::
ClassIntersection
&&
ClassSetOperand
1. 令 A 为
CompileToCharSet
作用于
ClassIntersection 的结果,其中参数为
rer 。
2. 令 B 为
CompileToCharSet
作用于
ClassSetOperand 的结果,其中参数为
rer 。
3. 返回
CharSets
A 和 B 的交集。
ClassSubtraction
::
ClassSetOperand
--
ClassSetOperand
1. 令 A 为
CompileToCharSet
作用于
ClassSetOperand 的结果,其中参数为
rer 。
2. 令 B 为
CompileToCharSet
作用于
ClassSetOperand 的结果,其中参数为
rer 。
3. 返回
CharSet
包含 A 的 CharSetElements 中不属于 B 的元素。
ClassSubtraction
::
ClassSubtraction
--
ClassSetOperand
1. 令 A 为
CompileToCharSet
作用于
ClassSubtraction 的结果,其中参数为
rer 。
2. 令 B 为
CompileToCharSet
作用于
ClassSetOperand 的结果,其中参数为
rer 。
3. 返回
CharSet
包含 A 的 CharSetElements 中不属于 B 的元素。
ClassSetRange
::
ClassSetCharacter
-
ClassSetCharacter
1. 令 A 为
CompileToCharSet
作用于
ClassSetCharacter 的结果,其中参数为
rer 。
2. 令 B 为
CompileToCharSet
作用于
ClassSetCharacter 的结果,其中参数为
rer 。
3. 返回
MaybeSimpleCaseFolding
(rer ,
CharacterRange
(A , B )).
Note 6
结果通常会包含两个或更多的范围。当 UnicodeSets 为 true 并且 IgnoreCase 为 true
时,
MaybeSimpleCaseFolding
(rer , [Ā-č]) 将仅包括该范围中的奇数码点。
ClassSetOperand
:: ClassSetCharacter
1. 让 A 为 CompileToCharSet 的
ClassSetCharacter ,
参数为 rer 。
2. 返回 MaybeSimpleCaseFolding (rer ,
A )。
ClassSetOperand
:: ClassStringDisjunction
1. 让 A 为 CompileToCharSet 的
ClassStringDisjunction
,参数为 rer 。
2. 返回 MaybeSimpleCaseFolding (rer ,
A )。
ClassSetOperand
:: NestedClass
1. 返回 CompileToCharSet 的
NestedClass
,参数为 rer 。
NestedClass
::
[
ClassContents
]
1. 返回 CompileToCharSet 的
ClassContents
,参数为 rer 。
NestedClass
::
[^
ClassContents
]
1. 让 A 为 CompileToCharSet 的
ClassContents ,
参数为 rer 。
2. 返回 CharacterComplement (rer ,
A )。
NestedClass
::
\
CharacterClassEscape
1. 返回 CompileToCharSet 的
CharacterClassEscape
,参数为 rer 。
ClassStringDisjunction
::
\q{
ClassStringDisjunctionContents
}
1. 返回 CompileToCharSet 的
ClassStringDisjunctionContents
,参数为 rer 。
ClassStringDisjunctionContents
:: ClassString
1. 让 s 为 CompileClassSetString
的 ClassString
,参数为 rer 。
2. 返回包含一个字符串 s 的 CharSet 。
ClassStringDisjunctionContents
::
ClassString
|
ClassStringDisjunctionContents
1. 让 s 为 CompileClassSetString
的 ClassString
,参数为 rer 。
2. 让 A 为包含一个字符串 s 的 CharSet 。
3. 让 B 为 CompileToCharSet 的
ClassStringDisjunctionContents
,参数为 rer 。
4. 返回 CharSets 的
A 和 B 的并集。
ClassSetCharacter
::
SourceCharacter
但不包括 ClassSetSyntaxCharacter
\
CharacterEscape
\
ClassSetReservedPunctuator
1. 让 cv 为该 ClassSetCharacter 的
CharacterValue 。
2. 让 c 为字符值为 cv 的字符。
3. 返回包含单个字符 c 的 CharSet 。
ClassSetCharacter
:: \b
1. 返回包含单个字符 U+0008 (BACKSPACE) 的 CharSet 。
22.2.2.9.1 CharacterRange ( A , B )
抽象操作 CharacterRange 接受参数 A (一个 CharSet )和
B (一个 CharSet ),并返回一个 CharSet 。调用时执行以下步骤:
1. 断言 :A 和 B
每个都包含恰好一个字符。
2. 让 a 为 CharSet
A 中的那个字符。
3. 让 b 为 CharSet
B 中的那个字符。
4. 让 i 为字符 a 的字符值。
5. 让 j 为字符 b 的字符值。
6. 断言 :i ≤ j 。
7. 返回包含字符值在从 i 到 j 的 闭区间 内的所有字符的 CharSet 。
22.2.2.9.2 HasEitherUnicodeFlag ( rer )
抽象操作 HasEitherUnicodeFlag 接受参数 rer (一个 RegExp
记录 ),并返回一个布尔值。调用时执行以下步骤:
1. 如果 rer .[[Unicode]] 为
true 或 rer .[[UnicodeSets]] 为
true ,则
a. 返回 true 。
2. 返回 false 。
22.2.2.9.3 WordCharacters ( rer )
抽象操作 WordCharacters 接受参数 rer (一个 RegExp 记录 ),并返回一个 CharSet 。返回一个包含“单词字符”的 CharSet ,这些字符用于
\b
、\B
、\w
和 \W
。调用时执行以下步骤:
1. 让 basicWordChars 成为一个 CharSet ,包含所有的 ASCII 单词字符 。
2. 让 extraWordChars 成为一个 CharSet ,包含所有字符 c ,使得
c 不在 basicWordChars 中,但 Canonicalize (rer ,c )
在 basicWordChars 中。
3. Assert :extraWordChars 为空,除非
HasEitherUnicodeFlag (rer )
为 true 且 rer .[[IgnoreCase]] 为
true 。
4. 返回 basicWordChars 和 extraWordChars 的并集。
22.2.2.9.4 AllCharacters ( rer )
抽象操作 AllCharacters 接受参数 rer (一个 RegExp 记录 ),并返回一个 CharSet 。根据正则表达式标志返回“所有字符”的集合。调用时执行以下步骤:
1. 如果 rer .[[UnicodeSets]] 为
true 且 rer .[[IgnoreCase]] 为
true ,则
a. 返回一个 CharSet ,包含所有没有 简单大小写折叠 映射的 Unicode
代码点(即,scf (c )=c )。
2. 否则,如果 HasEitherUnicodeFlag (rer )
为 true ,则
a. 返回一个 CharSet ,包含所有代码点值。
3. 否则,
a. 返回一个 CharSet ,包含所有代码单元值。
22.2.2.9.5 MaybeSimpleCaseFolding ( rer , A )
抽象操作 MaybeSimpleCaseFolding 接受两个参数:rer (一个 RegExp 记录 )和
A (一个 CharSet ),并返回一个 CharSet 。如果 rer .[[UnicodeSets]] 为 false 或 rer .[[IgnoreCase]] 为 false ,则返回 A 。
否则,它使用 简单大小写折叠
(scf(cp ) )定义在 Unicode 字符数据库的
CaseFolding.txt
文件中(每个映射将一个代码点映射到另一个代码点)逐字符地将 A 的每个 CharSetElement
映射到规范形式,并返回结果 CharSet 。调用时执行以下步骤:
1. 如果 rer .[[UnicodeSets]]
为 false 或 rer .[[IgnoreCase]] 为
false ,则返回 A 。
2. 让 B 成为一个新的空 CharSet 。
3. 对 A 的每个 CharSetElement
s 执行以下操作:
a. 让 t 成为一个空的字符序列。
b. 对 s 中的每个单一代码点 cp 执行:
i. 将 scf (cp ) 附加到
t 。
c. 将 t 添加到 B 。
4. 返回 B 。
22.2.2.9.6 CharacterComplement ( rer , S )
抽象操作 CharacterComplement 接受两个参数:rer (一个 RegExp 记录 )和
S (一个 CharSet ),并返回一个 CharSet 。调用时执行以下步骤:
1. 让 A 为 AllCharacters (rer )。
2. 返回一个 CharSet ,包含 A 中的
CharSetElements,而这些 CharSetElements 不在 S 中。
22.2.2.9.7 UnicodeMatchProperty ( rer , p )
抽象操作 UnicodeMatchProperty 接受两个参数:rer (一个 正则表达式记录 )和
p (ECMAScript 源文本 ),并返回一个 Unicode
属性名称 。当调用时,它执行以下步骤:
1. 如果 rer .[[UnicodeSets]] 是
true 且 p 是在 表
69 中“属性名称 ”列中列出的 Unicode
属性名称 ,那么
a. 返回属性 p 的 Unicode 代码点的 列表 。
2. 断言 :p 是在 表 67 或
表 68
中“属性名称 及别名”列中列出的 Unicode 属性名称 或属性别名。
3. 令 c 为 p 的标准化
属性名称 ,如在相应行的“标准化 属性名称 ”列中所示。
4. 返回标准化属性 c 的 Unicode 代码点的 列表 。
实现必须支持在 表 67 、表 68 和
表 69 中列出的
Unicode 属性名称和别名。为确保互操作性,实施不得支持任何其他属性名称或别名。
注 1
例如,Script_Extensions
(属性名称 )和
scx
(属性别名)是有效的,但 script_extensions
或
Scx
不是。
注 2
列出的属性组成了 UTS18 RL1.2 所要求的超集。
注 3
这些表格中的条目的拼写(包括大小写)与 Unicode 字符数据库中的文件 PropertyAliases.txt
中使用的拼写匹配。该文件中的精确拼写是 保证稳定的 。
表 67: 非二进制 Unicode 属性别名及其标准化属性名称
表 68:二进制 Unicode 属性别名及其标准化属性名称
表 69:字符串的二进制 Unicode 属性
属性名称
Basic_Emoji
Emoji_Keycap_Sequence
RGI_Emoji_Modifier_Sequence
RGI_Emoji_Flag_Sequence
RGI_Emoji_Tag_Sequence
RGI_Emoji_ZWJ_Sequence
RGI_Emoji
22.2.2.9.8 UnicodeMatchPropertyValue ( p , v )
抽象操作 UnicodeMatchPropertyValue 接受两个参数 p (ECMAScript 源文本 )和
v
(ECMAScript 源文本 ),并返回一个 Unicode
属性值。调用时执行以下步骤:
1. 断言 :p 是一个规范的、未别名的 Unicode
属性名称 ,在 表 67
的“规范属性名称”列中列出。
2. 断言 :v 是 Unicode 属性 p
的属性值或属性值别名,在 PropertyValueAliases.txt
中列出。
3. 令 value 为 v 的规范属性值,如对应行的“规范属性值”列中所给出。
4. 返回 Unicode 代码点的 列表
value 。
实现必须支持 PropertyValueAliases.txt
中列出的 Unicode 属性值和属性值别名,针对在 表 67
中列出的属性。为了确保互操作性,实施不得支持任何其他属性值或属性值别名。
注 1
例如,Xpeo
和 Old_Persian
是有效的 Script_Extensions
值,但
xpeo
和 Old Persian
不是。
注 2
此算法与 UAX44 中列出的符号值匹配规则
有所不同:不忽略大小写、空白字符 、U+002D(连字符)和
U+005F(下划线),且不支持
Is
前缀。
22.2.2.10 运行时语义: CompileClassSetString
语法导向操作
CompileClassSetString 接受参数 rer (RegExp 记录 ),并返回一系列字符。它在以下产生式上分段定义:
ClassString
:: [empty]
1. 返回一个空字符序列。
ClassString
:: NonEmptyClassString
1. 返回 CompileClassSetString
对 NonEmptyClassString
的结果,参数为 rer 。
NonEmptyClassString
::
ClassSetCharacter
NonEmptyClassString opt
1. 令 cs 为 CompileToCharSet 对
ClassSetCharacter 的结果,参数为
rer 。
2. 令 s1 为 cs 的单个 CharSetElement 序列。
3. 如果存在 NonEmptyClassString ,则
a. 令 s2 为 CompileClassSetString
对 NonEmptyClassString
的结果,参数为 rer 。
b. 返回 s1 和 s2 的连接。
4. 返回 s1 。
22.2.3 用于 RegExp 创建的抽象操作
22.2.3.1 RegExpCreate ( P , F )
抽象操作 RegExpCreate 接受参数 P (一个 ECMAScript 语言值 )和
F (一个字符串或 undefined ),返回一个 包含 对象的正常完成或一个
抛出完成 。它在调用时执行以下步骤:
1. 令 obj 为 ! RegExpAlloc (%RegExp% )。
2. 返回 ? RegExpInitialize (obj , P ,
F )。
22.2.3.2 RegExpAlloc ( newTarget )
抽象操作 RegExpAlloc 接受参数 newTarget (一个 构造函数 ),返回一个包含对象的 正常完成 或一个
抛出完成 。它在调用时执行以下步骤:
1. 令 obj 为 ? OrdinaryCreateFromConstructor (newTarget ,
"%RegExp.prototype%" , « [[OriginalSource]] , [[OriginalFlags]] , [[RegExpRecord]] , [[RegExpMatcher]] »)。
2. 执行 ! DefinePropertyOrThrow (obj ,
"lastIndex" , PropertyDescriptor { [[Writable]] :
true , [[Enumerable]] : false , [[Configurable]] : false })。
3. 返回 obj 。
22.2.3.3 RegExpInitialize ( obj , pattern ,
flags )
抽象操作 RegExpInitialize 接受参数 obj (一个对象),
pattern
(一个 ECMAScript 语言值 ),和
flags (一个 ECMAScript
语言值 ),返回一个 包含 对象的正常完成或一个
抛出完成 。它在调用时执行以下步骤:
1. 如果 pattern 是 undefined ,令
P 为空字符串。
2. 否则,令 P 为 ? ToString (pattern )。
3. 如果 flags 是 undefined ,令
F 为空字符串。
4. 否则,令 F 为 ? ToString (flags )。
5. 如果 F 包含 "d" ,
"g" ,
"i" , "m" , "s" , "u" ,
"v" , 或 "y" 以外的任何代码单元,或
如果 F 包含任何代码单元超过一次,则抛出 SyntaxError
异常。
6. 如果 F 包含 "i" ,令
i
为 true ;否则令 i 为 false 。
7. 如果 F 包含 "m" ,令
m
为 true ;否则令 m 为 false 。
8. 如果 F 包含 "s" ,令
s
为 true ;否则令 s 为 false 。
9. 如果 F 包含 "u" ,令
u
为 true ;否则令 u 为 false 。
10. 如果 F 包含 "v" ,令
v 为 true ;否则令 v 为 false 。
11. 如果 u 是 true 或 v
是
true ,则
a. 令 patternText 为 StringToCodePoints (P )。
12. 否则,
a. 令 patternText 为解释
P 的每个 16 位元素作为 Unicode BMP 代码点的结果。UTF-16 解码不适用于
这些元素。
13. 令 parseResult 为 ParsePattern (patternText ,
u , v )。
14. 如果 parseResult 是非空的 列表 的
SyntaxError 对象,抛出 SyntaxError 异常。
15. 断言 : parseResult 是一个
模式
解析节点 。
16. 设置 obj 的 [[OriginalSource]]
为 P 。
17. 设置 obj 的 [[OriginalFlags]]
为
F 。
18. 令 capturingGroupsCount 为 CountLeftCapturingParensWithin (parseResult )。
19. 令 rer 为 正则表达式
记录 { [[IgnoreCase]] : i , [[Multiline]] : m , [[DotAll]] :
s ,
[[Unicode]] : u , [[UnicodeSets]] :
v , [[CapturingGroupsCount]] :
capturingGroupsCount }。
20. 设置 obj 的 [[RegExpRecord]]
为
rer 。
21. 设置 obj 的 [[RegExpMatcher]]
为
CompilePattern 的
parseResult 参数 rer 。
22. 执行 ? 设置 (obj , "lastIndex" ,
+0 𝔽 , true )。
23. 返回 obj 。
22.2.3.4 静态语义:ParsePattern ( patternText ,
u , v )
抽象操作 ParsePattern 接受参数 patternText (一个 Unicode 代码点序列),u (一个布尔值),和
v (一个布尔值),返回一个 解析节点 或一个非空的 列表 的
SyntaxError 对象。
注
它在调用时执行以下步骤:
1. 如果 v 是 true 并且 u
是
true ,则
a. 令 parseResult 为一个 列表
,包含一个或多个 SyntaxError 对象。
2. 否则如果 v 是 true ,则
a. 令 parseResult 为 ? ParseText (patternText ,
模式 [+UnicodeMode,
+UnicodeSetsMode, +NamedCaptureGroups] )。
3. 否则如果 u 是 true ,则
a. 令 parseResult 为 ? ParseText (patternText ,
模式 [+UnicodeMode,
~UnicodeSetsMode, +NamedCaptureGroups] )。
4. 否则,
a. 令 parseResult 为 ? ParseText (patternText ,
模式 [~UnicodeMode,
~UnicodeSetsMode, +NamedCaptureGroups] )。
5. 返回 parseResult 。
22.2.4 RegExp 构造函数
RegExp 构造函数 :
是 %RegExp% 。
是 "RegExp" 属性的初始值 全局对象 。
在作为 构造函数 调用时,创建并初始化一个新的 RegExp 对象。
当作为函数而不是 构造函数 调用时,返回一个新的
RegExp 对象,或者如果唯一的参数是一个 RegExp 对象,则返回该参数本身。
可以用作类定义的 extends
子句的值。继承指定 RegExp 行为的子类 构造函数 必须包含对 RegExp 构造函数
的
super
调用,以使用必要的内部槽来创建和初始化子类实例。
22.2.4.1 RegExp ( pattern , flags )
此函数在调用时执行以下步骤:
1. 令 patternIsRegExp 为 ? IsRegExp (pattern )。
2. 如果 NewTarget 是 undefined ,则
a. 令 newTarget 为 活动函数对象 。
b. 如果 patternIsRegExp 为 true
且
flags 为 undefined ,则
i. 令 patternConstructor 为 ? Get (pattern ,
"constructor" )。
ii. 如果 SameValue (newTarget ,
patternConstructor ) 为 true ,则返回 pattern 。
3. 否则,
a. 令 newTarget 为 NewTarget。
4. 如果 pattern 是一个对象
且 pattern 有 [[RegExpMatcher]] 内部槽,则
a. 令 P 为 pattern 的 [[OriginalSource]] 。
b. 如果 flags 是 undefined ,令
F 为 pattern 的 [[OriginalFlags]] 。
c. 否则,令 F 为 flags 。
5. 否则如果 patternIsRegExp 为
true ,则
a. 令 P 为 ? Get (pattern , "source" )。
b. 如果 flags 是 undefined ,则
i. 令 F 为 ? Get (pattern ,
"flags" )。
c. 否则,
i. 令 F 为 flags 。
6. 否则,
a. 令 P 为 pattern 。
b. 令 F 为 flags 。
7. 令 O 为 ? RegExpAlloc (newTarget )。
8. 返回 ? RegExpInitialize (O , P , F )。
注
如果使用 StringLiteral
提供模式,则在此函数处理字符串之前,会执行通常的转义序列替换。如果
模式必须包含一个转义序列才能被此函数识别,则任何 U+005C(反斜杠)代码点必须在 StringLiteral 中转义,以防止它们在形成
StringLiteral
的内容时被移除。
22.2.5 RegExp 构造函数的属性
RegExp 构造函数 :
22.2.5.1 RegExp.prototype
RegExp.prototype
的初始值是 RegExp
原型对象 。
此属性具有属性 { [[Writable]] : false ,
[[Enumerable]] : false , [[Configurable]] :
false }.
22.2.5.2 get RegExp [ @@species ]
RegExp[@@species]
是一个 访问器属性 ,其 set 访问器函数为
undefined 。它的 get 访问器函数在调用时执行以下步骤:
1. 返回 this 值。
此函数的 "name" 属性的值为 "get
[Symbol.species]" 。
注
RegExp 原型方法通常使用它们的 this 值的 构造函数 来创建一个派生对象。然而,子类 构造函数 可以通过重新定义其 @@species 属性来覆盖这种默认行为。
22.2.6 RegExp 原型对象的属性
RegExp 原型对象 :
是 %RegExp.prototype% 。
是一个 普通对象 。
不是 RegExp 实例,并且没有 [[RegExpMatcher]] 内部槽
或
任何 RegExp 实例对象的其他内部槽。
具有 [[Prototype]] 内部槽,其值为 %Object.prototype% 。
注
RegExp 原型对象没有自己的 "valueOf" 属性;
然而,
它继承了 "valueOf" 属性自 Object
原型对象 。
22.2.6.1 RegExp.prototype.constructor
RegExp.prototype.constructor
的初始值是 %RegExp% 。
22.2.6.2 RegExp.prototype.exec ( string )
此方法在 string 中搜索正则表达式模式的出现,并返回包含匹配结果的数组,或者如果 string 未匹配,则返回 null 。
它在调用时执行以下步骤:
1. 令 R 为 this 值。
2. 执行 ? RequireInternalSlot (R ,
[[RegExpMatcher]] )。
3. 令 S 为 ? ToString (string )。
4. 返回 ? RegExpBuiltinExec (R , S )。
22.2.6.3 get RegExp.prototype.dotAll
RegExp.prototype.dotAll
是一个 访问器属性 ,其 set 访问器函数为
undefined 。它的 get 访问器函数在调用时执行以下步骤:
1. 令 R 为 this 值。
2. 令 cu 为代码单元 0x0073(拉丁小写字母 S)。
3. 返回 ? RegExpHasFlag (R ,
cu )。
22.2.6.4 get RegExp.prototype.flags
RegExp.prototype.flags
是一个 访问器属性 ,其 set 访问器函数为
undefined 。它的 get 访问器函数在调用时执行以下步骤:
1. 令 R 为 this 值。
2. 如果 R 不是一个对象 ,抛出
TypeError 异常。
3. 令 codeUnits 为一个新的空的 列表 。
4. 令 hasIndices 为 ToBoolean (?
Get (R , "hasIndices" ))。
5. 如果 hasIndices 为 true ,将代码单元
0x0064(拉丁小写字母 D)附加到 codeUnits 。
6. 令 global 为 ToBoolean (?
Get (R , "global" ))。
7. 如果 global 为 true ,将代码单元
0x0067(拉丁小写字母
G)附加到 codeUnits 。
8. 令 ignoreCase 为 ToBoolean (?
Get (R , "ignoreCase" ))。
9. 如果 ignoreCase 为 true ,将代码单元
0x0069(拉丁小写字母 I)附加到 codeUnits 。
10. 令 multiline 为 ToBoolean (?
Get (R , "multiline" ))。
11. 如果 multiline 为 true ,将代码单元
0x006D(拉丁小写字母 M)附加到 codeUnits 。
12. 令 dotAll 为 ToBoolean (?
Get (R , "dotAll" ))。
13. 如果 dotAll 为 true ,将代码单元
0x0073(拉丁小写字母
S)附加到 codeUnits 。
14. 令 unicode 为 ToBoolean (?
Get (R , "unicode" ))。
15. 如果 unicode 为 true ,将代码单元
0x0075(拉丁小写字母 U)附加到 codeUnits 。
16. 令 unicodeSets 为 ToBoolean (?
Get (R , "unicodeSets" ))。
17. 如果 unicodeSets 为 true ,将代码单元
0x0076(拉丁小写字母 V)附加到 codeUnits 。
18. 令 sticky 为 ToBoolean (?
Get (R , "sticky" ))。
19. 如果 sticky 为 true ,将代码单元
0x0079(拉丁小写字母
Y)附加到 codeUnits 。
20. 返回其代码单元是 列表
codeUnits 的字符串值。如果 codeUnits 没有元素,则返回空字符串。
22.2.6.4.1 RegExpHasFlag ( R , codeUnit )
抽象操作 RegExpHasFlag 接受参数 R (一个 ECMAScript
语言值 )和 codeUnit (一个代码单元),返回一个 包含 布尔值或
undefined 的正常完成,或一个 抛出完成 。它在调用时执行以下步骤:
1. 如果 R 不是一个对象 ,抛出
TypeError 异常。
2. 如果 R 没有 [[OriginalFlags]]
内部槽,则
a. 如果 SameValue (R ,
%RegExp.prototype% )
为 true ,返回 undefined 。
b. 否则,抛出 TypeError 异常。
3. 令 flags 为 R 的 [[OriginalFlags]] 。
4. 如果 flags 包含 codeUnit ,返回
true 。
5. 返回 false 。
22.2.6.5 get RegExp.prototype.global
RegExp.prototype.global
是一个 访问器属性 ,其 set 访问器函数为
undefined 。它的 get 访问器函数在调用时执行以下步骤:
1. 令 R 为 this 值。
2. 令 cu 为代码单元 0x0067(拉丁小写字母 G)。
3. 返回 ? RegExpHasFlag (R ,
cu )。
22.2.6.6 get RegExp.prototype.hasIndices
RegExp.prototype.hasIndices
是一个 访问器属性 ,其 set 访问器函数为
undefined 。它的 get 访问器函数在调用时执行以下步骤:
1. 令 R 为 this 值。
2. 令 cu 为代码单元 0x0064(拉丁小写字母 D)。
3. 返回 ? RegExpHasFlag (R ,
cu )。
22.2.6.7 get RegExp.prototype.ignoreCase
RegExp.prototype.ignoreCase
是一个 访问器属性 ,其 set 访问器函数为
undefined 。它的 get 访问器函数在调用时执行以下步骤:
1. 令 R 为 this 值。
2. 令 cu 为代码单元 0x0069(拉丁小写字母 I)。
3. 返回 ? RegExpHasFlag (R ,
cu )。
22.2.6.8 RegExp.prototype [ @@match ] ( string )
此方法在调用时执行以下步骤:
1. 令 rx 为 this 值。
2. 如果 rx 不是一个对象 ,抛出
TypeError 异常。
3. 令 S 为 ? ToString (string )。
4. 令 flags 为 ? ToString (? Get (rx ,
"flags" ))。
5. 如果 flags 不包含 "g" ,则
a. 返回 ? RegExpExec (rx , S )。
6. 否则,
a. 如果 flags 包含 "u" 或
flags 包含 "v" ,则令 fullUnicode 为
true 。否则,令 fullUnicode 为 false 。
b. 执行 ? Set (rx , "lastIndex" ,
+0 𝔽 , true )。
c. 令 A 为 ! ArrayCreate (0)。
d. 令 n 为 0。
e. 重复,
i. 令 result 为 ? RegExpExec (rx , S )。
ii. 如果 result 为 null ,则
1. 如果 n = 0,返回
null 。
2. 返回 A 。
iii. 否则,
1. 令 matchStr 为 ? ToString (? Get (result ,
"0" ))。
2. 执行 ! CreateDataPropertyOrThrow (A ,
! ToString (𝔽 (n )),
matchStr )。
3. 如果 matchStr 是空字符串,则
a. 令 thisIndex 为 ℝ (?
ToLength (? Get (rx ,
"lastIndex" )))。
b. 令 nextIndex 为 AdvanceStringIndex (S ,
thisIndex , fullUnicode )。
c. 执行 ? Set (rx ,
"lastIndex" , 𝔽 (nextIndex ),
true )。
4. 将 n 设置为 n + 1。
此方法的 "name" 属性的值为
"[Symbol.match]" 。
注
@@match 属性由 IsRegExp 抽象操作用于
标识具有正则表达式基本行为的对象。缺少 @@match 属性或存在其值不转换为布尔值
true 的属性
表明该对象不打算用作正则表达式对象。
22.2.6.9 RegExp.prototype [ @@matchAll ] ( string )
此方法在调用时执行以下步骤:
1. 令 R 为 this 值。
2. 如果 R 不是一个对象 ,抛出
TypeError 异常。
3. 令 S 为 ? ToString (string )。
4. 令 C 为 ? SpeciesConstructor (R , %RegExp% )。
5. 令 flags 为 ? ToString (? Get (R ,
"flags" ))。
6. 令 matcher 为 ? Construct (C , « R ,
flags »)。
7. 令 lastIndex 为 ? ToLength (? Get (R ,
"lastIndex" ))。
8. 执行 ? Set (matcher , "lastIndex" ,
lastIndex , true )。
9. 如果 flags 包含 "g" ,则令
global 为 true 。
10. 否则,令 global 为 false 。
11. 如果 flags 包含 "u" 或
flags 包含 "v" ,则令 fullUnicode 为
true 。
12. 否则,令 fullUnicode 为
false 。
13. 返回 CreateRegExpStringIterator (matcher ,
S , global , fullUnicode )。
此方法的 "name" 属性的值为
"[Symbol.matchAll]" 。
22.2.6.10 get RegExp.prototype.multiline
RegExp.prototype.multiline
是一个 访问器属性 ,其 set 访问器函数为
undefined 。它的 get 访问器函数在调用时执行以下步骤:
1. 令 R 为 this 值。
2. 令 cu 为代码单元 0x006D(拉丁小写字母 M)。
3. 返回 ? RegExpHasFlag (R ,
cu )。
22.2.6.11 RegExp.prototype [ @@replace ] ( string ,
replaceValue )
此方法在调用时执行以下步骤:
1. 令 rx 为 this 值。
2. 如果 rx 不是一个对象 ,抛出
TypeError 异常。
3. 令 S 为 ? ToString (string )。
4. 令 lengthS 为 S 的长度。
5. 令 functionalReplace 为 IsCallable (replaceValue )。
6. 如果 functionalReplace 为 false ,
则
a. 将 replaceValue 设置为 ? ToString (replaceValue )。
7. 令 flags 为 ? ToString (? Get (rx ,
"flags" ))。
8. 如果 flags 包含 "g" ,令
global 为 true 。否则,令 global 为 false 。
9. 如果 global 为 true ,则
a. 执行 ? Set (rx , "lastIndex" ,
+0 𝔽 , true )。
10. 令 results 为一个新的空的 列表 。
11. 令 done 为 false 。
12. 重复,直到 done 为 false ,
a. 令 result 为 ? RegExpExec (rx , S )。
b. 如果 result 为 null ,则
i. 将 done 设置为 true 。
c. 否则,
i. 将 result 附加到 results 。
ii. 如果 global 为 false ,
则
1. 将 done 设置为 true 。
iii. 否则,
1. 令 matchStr 为 ? ToString (? Get (result ,
"0" ))。
2. 如果 matchStr 是空字符串,则
a. 令 thisIndex 为 ℝ (?
ToLength (? Get (rx ,
"lastIndex" )))。
b. 如果 flags 包含 "u" 或
flags 包含 "v" ,则令 fullUnicode 为
true 。否则,令 fullUnicode 为 false 。
c. 令 nextIndex 为 AdvanceStringIndex (S ,
thisIndex , fullUnicode )。
d. 执行 ? Set (rx ,
"lastIndex" , 𝔽 (nextIndex ),
true )。
13. 令 accumulatedResult 为空字符串。
14. 令 nextSourcePosition 为 0。
15. 对于 results 中的每个元素 result ,执行
a. 令 resultLength 为 ? LengthOfArrayLike (result )。
b. 令 nCaptures 为 最大值 (resultLength - 1,
0)。
c. 令 matched 为 ? ToString (? Get (result , "0" ))。
d. 令 matchLength 为 matched 的长度。
e. 令 position 为 ? ToIntegerOrInfinity (? Get (result , "index" ))。
f. 将 position 设置为 限制 在 0 和
lengthS 之间的结果。
g. 令 captures 为一个新的空的 列表 。
h. 令 n 为 1。
i. 重复,直到 n ≤ nCaptures ,
i. 令 capN 为 ? Get (result , ! ToString (𝔽 (n )))。
ii. 如果 capN 不是 undefined ,
则
1. 将 capN 设置为 ? ToString (capN )。
iii. 将 capN 添加到 captures 。
iv. 注意:当 n = 1 时,上一步将第一个元素放入
captures (在索引 0 处)。更一般地,第 n 个捕获(由第 n 组捕获括号捕获的字符)位于
captures [n - 1]。
v. 将 n 设置为 n + 1。
j. 令 namedCaptures 为 ? Get (result , "groups" )。
k. 如果 functionalReplace 为 true ,
则
i. 令 replacerArgs 为 « matched »、
captures 和 « 𝔽 (position )、S »
的 列表连接 。
ii. 如果 namedCaptures 不是
undefined ,则
1. 将 namedCaptures 添加到
replacerArgs 。
iii. 令 replValue 为 ? Call (replaceValue ,undefined ,replacerArgs )。
iv. 令 replacement 为 ? ToString (replValue )。
l. 否则,
i. 如果 namedCaptures 不是
undefined ,则
1. 将 namedCaptures 设置为 ? ToObject (namedCaptures )。
ii. 令 replacement 为 ? GetSubstitution (matched ,S ,position ,captures ,namedCaptures ,replaceValue )。
m. 如果 position ≥ nextSourcePosition ,则
i. 注意:position
通常不应向后移动。如果确实如此,这表明正则表达式子类行为不当或使用触发的副作用来更改全局标志或 rx 的其他特性。在这种情况下,相应的替换将被忽略。
ii. 将 accumulatedResult 设置为
accumulatedResult 、S 从 nextSourcePosition 到
position
的 子字符串 和 replacement 的
字符串连接 结果。
iii. 将 nextSourcePosition 设置为 position
+
matchLength 。
16. 如果 nextSourcePosition ≥ lengthS ,
返回
accumulatedResult 。
17. 返回 accumulatedResult 和 S 从
nextSourcePosition 的 子字符串 的 字符串连接 结果。
此方法的 "name" 属性的值为
"[Symbol.replace]" 。
22.2.6.12 RegExp.prototype [ @@search ] ( string )
调用此方法时执行以下步骤:
1. 令 rx 为 this 值。
2. 如果 rx 不是一个对象 ,则抛出
TypeError 异常。
3. 令 S 为 ? ToString (string )。
4. 令 previousLastIndex 为 ? Get (rx , "lastIndex" )。
5. 如果 SameValue (previousLastIndex ,
+0 𝔽 ) 为 false ,则
a. 执行 ? Set (rx , "lastIndex" ,
+0 𝔽 , true )。
6. 令 result 为 ? RegExpExec (rx , S )。
7. 令 currentLastIndex 为 ? Get (rx , "lastIndex" )。
8. 如果 SameValue (currentLastIndex ,
previousLastIndex ) 为 false ,则
a. 执行 ? Set (rx , "lastIndex" ,
previousLastIndex , true )。
9. 如果 result 为 null ,返回
-1 𝔽 。
10. 返回 ? Get (result , "index" )。
此方法的 "name" 属性的值为 "[Symbol.search]" 。
注
在执行搜索时,会忽略此 RegExp 对象的 "lastIndex" 和 "global" 属性。
"lastIndex" 属性保持不变。
22.2.6.13 get RegExp.prototype.source
RegExp.prototype.source
是一个 访问器属性 ,其 set 访问器函数为
undefined 。调用其 get 访问器函数时执行以下步骤:
1. 令 R 为 this 值。
2. 如果 R 不是一个对象 ,则抛出
TypeError 异常。
3. 如果 R 没有 [[OriginalSource]]
内部槽,那么
a. 如果 SameValue (R ,%RegExp.prototype% )
为 true ,则返回 "(?:)" 。
b. 否则,抛出 TypeError 异常。
4. 断言 :R 有一个 [[OriginalFlags]] 内部槽。
5. 令 src 为 R 的 [[OriginalSource]] 。
6. 令 flags 为 R 的 [[OriginalFlags]] 。
7. 返回 EscapeRegExpPattern (src ,flags )。
22.2.6.13.1 EscapeRegExpPattern ( P ,F )
抽象操作 EscapeRegExpPattern 接受参数 P (一个字符串)和 F (一个字符串),并返回一个字符串。调用时执行以下步骤:
1. 如果 F 包含 "v" ,那么
a. 令 patternSymbol 为 Pattern [+UnicodeMode,
+UnicodeSetsMode] 。
2. 否则,如果 F 包含 "u" ,那么
a. 令 patternSymbol 为 Pattern [+UnicodeMode,
~UnicodeSetsMode] 。
3. 否则,
a. 令 patternSymbol 为 Pattern [~UnicodeMode,
~UnicodeSetsMode] 。
4. 令 S 为 patternSymbol 形式的字符串,其等同于将
P 解释为 UTF-16 编码的 Unicode 代码点(6.1.4 ),其中某些代码点按下述方式转义。S
可能与 P 相同或不同;然而,通过评估 S 作为 patternSymbol 所产生的 抽象闭包 必须与构造对象的 [[RegExpMatcher]] 内部槽所给出的 抽象闭包
行为相同。使用相同的 P 和 F 值多次调用此抽象操作必须产生相同的结果。
5. 模式中的代码点 /
或任何 行终止符 应根据需要在 S
中转义,以确保
字符串连接
"/" 、S 、"/" 和 F 可以作为 正则表达式字面量
进行解析(在适当的词法上下文中),其行为与构造的正则表达式相同。例如,如果 P 是 "/" ,那么 S 可以是
"\/" 或 "\u002F" ,但不能是 "/" ,因为
///
后跟 F 将被解析为 单行注释 而不是 正则表达式字面量 。如果
P 是空字符串,则通过将 S 设为 "(?:)" 来满足此规范。
6. 返回 S 。
22.2.6.14 RegExp.prototype [ @@split ] ( string , limit
)
注 1
该方法返回一个数组,其中存储了将 string 转换为字符串后的子字符串。这些子字符串是通过从左到右搜索 this
值的正则表达式的匹配项来确定的;这些匹配项不是返回数组中任何字符串的一部分,而是用于划分字符串值。
this 值可以是一个空的正则表达式或可以匹配空字符串的正则表达式。在这种情况下,正则表达式不会匹配输入字符串开头或结尾的空
子字符串 ,也不会匹配前一个分隔符匹配项结尾的空
子字符串 。(例如,如果正则表达式匹配空字符串,则字符串会被分割成单个代码单元元素;结果数组的长度等于字符串的长度,每个
子字符串 包含一个代码单元。)在字符串的给定索引处,只考虑第一次匹配,即使回溯可以在该索引处产生非空的
子字符串 匹配。(例如,/a*?/[Symbol.split]("ab")
的计算结果为数组
["a", "b"]
,而 /a*/[Symbol.split]("ab")
的计算结果为数组 ["","b"]
。)
如果 string 是(或转换为)空字符串,结果取决于正则表达式是否可以匹配空字符串。如果可以,则结果数组不包含任何元素。否则,结果数组包含一个元素,即空字符串。
如果正则表达式包含捕获括号,则每次匹配 separator 时,捕获括号的结果(包括任何 undefined
结果)会被拼接到输出数组中。例如,
/<(\/)?([^<> ]+)>/[Symbol.split]("A<B > bold</B > and<CODE > coded</CODE > ")
计算结果为数组
["A" , undefined , "B" , "bold" , "/" , "B" , "and" , undefined , "CODE" , "coded" , "/" , "CODE" , "" ]
如果 limit 不是 undefined ,则输出数组会被截断,使其包含不超过 limit 个元素。
调用该方法时执行以下步骤:
1. 令 rx 为 this 值。
2. 如果 rx 不是一个对象 ,则抛出
TypeError 异常。
3. 令 S 为 ? ToString (string ).
4. 令 C 为 ? SpeciesConstructor (rx , %RegExp% ).
5. 令 flags 为 ? ToString (? Get (rx ,
"flags" )).
6. 如果 flags 包含 "u" 或 flags
包含
"v" ,令 unicodeMatching 为 true 。
7. 否则,令 unicodeMatching 为 false 。
8. 如果 flags 包含 "y" ,令
newFlags
为 flags 。
9. 否则,令 newFlags 为 字符串连接
flags 和 "y" 的结果。
10. 令 splitter 为 ? Construct (C , « rx ,
newFlags »).
11. 令 A 为 ! ArrayCreate (0).
12. 令 lengthA 为 0。
13. 如果 limit 为 undefined ,令
lim 为 2** 32 - 1;否则,令 lim 为 ℝ (? ToUint32 (limit )).
14. 如果 lim = 0,返回 A 。
15. 如果 S 是空字符串,则
a. 令 z 为 ? RegExpExec (splitter , S ).
b. 如果 z 不是 null ,返回 A 。
c. 执行 ! CreateDataPropertyOrThrow (A ,
"0" , S ).
d. 返回 A 。
16. 令 size 为 S 的长度。
17. 令 p 为 0。
18. 令 q 为 p 。
19. 重复,直到 q < size ,
a. 执行 ? Set (splitter , "lastIndex" ,
𝔽 (q ),
true ).
b. 令 z 为 ? RegExpExec (splitter , S ).
c. 如果 z 是 null ,则
i. 令 q 为 AdvanceStringIndex (S ,
q , unicodeMatching ).
d. 否则,
i. 令 e 为 ℝ (? ToLength (? Get (splitter ,
"lastIndex" ))).
ii. 令 e 为 min (e ,
size ).
iii. 如果 e = p ,则
1. 令 q 为 AdvanceStringIndex (S ,
q , unicodeMatching ).
iv. 否则,
1. 令 T 为 从 S 中截取
p 到 q 的子字符串 。
2. 执行 ! CreateDataPropertyOrThrow (A ,
! ToString (𝔽 (lengthA )),
T ).
3. 令 lengthA 为 lengthA + 1。
4. 如果 lengthA = lim ,返回
A 。
5. 令 p 为 e 。
6. 令 numberOfCaptures 为 ? LengthOfArrayLike (z ).
7. 令 numberOfCaptures 为 max (numberOfCaptures
- 1, 0).
8. 令 i 为 1。
9. 重复,直到 i ≤ numberOfCaptures ,
a. 令 nextCapture 为 ? Get (z , ! ToString (𝔽 (i ))).
b. 执行 ! CreateDataPropertyOrThrow (A ,
! ToString (𝔽 (lengthA )),
nextCapture ).
c. 令 i 为 i + 1。
d. 令 lengthA 为 lengthA + 1。
e. 如果 lengthA = lim ,返回
A 。
10. 令 q 为 p 。
20. 令 T 为 从 S 中截取 p 到 size
的子字符串 .
21. 执行 ! CreateDataPropertyOrThrow (A ,
! ToString (𝔽 (lengthA )),
T ).
22. 返回 A .
该方法的 "name" 属性值为 "[Symbol.split]" .
注 2
该方法忽略此 RegExp 对象的 "global" 和 "sticky" 属性的值。
22.2.6.15 get RegExp.prototype.sticky
RegExp.prototype.sticky
是一个 访问器属性 ,其 set 访问器函数的值为
undefined 。它的 get 访问器函数在被调用时执行以下步骤:
令 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 。
注
返回的字符串形式为 正则表达式字面量 ,其行为与此对象相同。
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 的正常完成 ,或抛出完成异常 。调用时执行以下步骤:
1. 令 exec 为 ? Get (R ,
"exec" )。
2. 如果 IsCallable (exec ) 为
true ,则
a. 令 result 为 ? Call (exec , R , « S »)。
b. 如果 result 不是对象 且
result 不是 null ,抛出 TypeError 异常。
c. 返回 result 。
3. 执行 ? RequireInternalSlot (R ,
[[RegExpMatcher]] )。
4. 返回 ? RegExpBuiltinExec (R , S )。
注
如果找不到可调用的 "exec" 属性,该算法将回退到尝试使用内置的 RegExp
匹配算法。这为编写针对早期版本的代码提供了兼容行为,因为早期大多数使用正则表达式的内置算法并不会动态查找 "exec" 属性。
22.2.7.2 RegExpBuiltinExec ( R , S )
抽象操作 RegExpBuiltinExec 接受参数 R (一个已初始化的 RegExp 实例)和 S (一个字符串),并返回包含正常完成 的Array
exotic object 或null ,或者抛出完成异常 。调用时执行以下步骤:
1. 令 length 为 S 的长度。
2. 令 lastIndex 为 ℝ (? ToLength (? Get (R ,
"lastIndex" )))。
3. 令 flags 为 R 的 [[OriginalFlags]] 。
4. 如果 flags 包含 "g" ,则令
global
为 true ;否则令 global 为 false 。
5. 如果 flags 包含 "y" ,则令
sticky
为 true ;否则令 sticky 为 false 。
6. 如果 flags 包含 "d" ,则令
hasIndices 为 true ;否则令 hasIndices 为 false 。
7. 如果 global 为 false 且
sticky
为 false ,则将 lastIndex 设为 0。
8. 令 matcher 为 R 的 [[RegExpMatcher]] 。
9. 如果 flags 包含 "u" 或 flags
包含
"v" ,则令 fullUnicode 为 true ;否则令 fullUnicode
为
false 。
10. 令 matchSucceeded 为 false 。
11. 如果 fullUnicode 为 true ,则令
input 为 StringToCodePoints (S )。否则,令
input 为一个 列表 ,其元素为
S 的码单元。
12. 注意:input 的每个元素都被视为一个字符。
13. 重复,直到 matchSucceeded 为 false ,
a. 如果 lastIndex 大于 length ,则
i. 如果 global 为 true 或
sticky 为 true ,则
1. 执行 ? Set (R , "lastIndex" ,
+0 𝔽 , true )。
ii. 返回 null 。
b. 令 inputIndex 为 input 中从 S 的
lastIndex 元素获得的字符的索引。
c. 令 r 为 matcher (input ,
inputIndex )。
d. 如果 r 是 failure ,则
i. 如果 sticky 为 true ,则
1. 执行 ? Set (R , "lastIndex" ,
+0 𝔽 , true )。
2. 返回 null 。
ii. 将 lastIndex 设为 AdvanceStringIndex (S ,
lastIndex , fullUnicode )。
e. 否则,
i. 断言 :r 是一个 MatchState 。
ii. 将 matchSucceeded 设为 true 。
14. 令 e 为 r 的 [[EndIndex]] 。
15. 如果 fullUnicode 为 true ,将
e
设为 GetStringIndex (S ,
e )。
16. 如果 global 为 true 或
sticky
为 true ,则
a. 执行 ? Set (R , "lastIndex" , 𝔽 (e ),
true )。
17. 令 n 为 r 的 [[Captures]] 中的元素数量。
18. 断言 :n = R 的 [[RegExpRecord]] 的 [[CapturingGroupsCount]] 。
19. 断言 :n < 2** 32 - 1。
20. 令 A 为 ! ArrayCreate (n + 1)。
21. 断言 :A 的
"length"
属性的数学值 为 n + 1。
22. 执行 ! CreateDataPropertyOrThrow (A ,
"index" , 𝔽 (lastIndex ))。
23. 执行 ! CreateDataPropertyOrThrow (A ,
"input" , S )。
24. 令 match 为 匹配记录 { [[StartIndex]] : lastIndex , [[EndIndex]] :
e }。
25. 令 indices 为一个新的空的 列表 。
26. 令 groupNames 为一个新的空的 列表 。
27. 将 match 追加到 indices 。
28. 令 matchedSubstr 为 GetMatchString (S ,
match )。
29. 执行 ! CreateDataPropertyOrThrow (A ,
"0" , matchedSubstr )。
30. 如果 R 包含任何 GroupName ,则
a. 令 groups 为 OrdinaryObjectCreate (null )。
b. 令 hasGroups 为 true 。
31. 否则,
a. 令 groups 为 undefined 。
b. 令 hasGroups 为 false 。
32. 执行 ! CreateDataPropertyOrThrow (A ,
"groups" , groups )。
33. 对于每个 整数 i ,1 ≤ i ≤
n ,按升序进行,
a. 令 captureI 为 r 的第 i 个元素 [[Captures]] 。
b. 如果 captureI 是 undefined ,则
i. 令 capturedValue 为
undefined 。
ii. 将 undefined 追加到 indices 。
c. 否则,
i. 令 captureStart 为 captureI 的 [[StartIndex]] 。
ii. 令 captureEnd 为 captureI 的 [[EndIndex]] 。
iii. 如果 fullUnicode 为 true ,则
1. 将 captureStart 设为 GetStringIndex (S ,
captureStart )。
2. 将 captureEnd 设为 GetStringIndex (S ,
captureEnd )。
iv. 令 capture 为 匹配记录 {
[[StartIndex]] : captureStart , [[EndIndex]] : captureEnd }。
v. 令 capturedValue 为 GetMatchString (S ,
capture )。
vi. 将 capture 追加到 indices 。
d. 执行 ! CreateDataPropertyOrThrow (A ,
! ToString (𝔽 (i )),
capturedValue )。
e. 如果 R 的第 i 个捕获组定义了一个 GroupName ,则
i. 令 s 为该 GroupName 的 CapturingGroupName 。
ii. 执行 ! CreateDataPropertyOrThrow (groups ,
s , capturedValue )。
iii. 将 s 追加到 groupNames 。
f. 否则,
i. 将 undefined 追加到 groupNames 。
34. 如果 hasIndices 为 true ,则
a. 令 indicesArray 为 MakeMatchIndicesIndexPairArray (S ,
indices , groupNames , hasGroups )。
b. 执行 ! CreateDataPropertyOrThrow (A ,
"indices" , indicesArray )。
35. 返回 A 。
22.2.7.3 AdvanceStringIndex ( S , index ,
unicode )
抽象操作 AdvanceStringIndex 接受参数 S (一个字符串),index (一个非负整数),和
unicode (一个布尔值),并返回一个整数。调用时执行以下步骤:
1. 断言 :index ≤ 2** 53 - 1。
2. 如果 unicode 为 false ,返回
index + 1。
3. 令 length 为 S 的长度。
4. 如果 index + 1 ≥ length ,返回 index +
1。
5. 令 cp 为 CodePointAt (S ,
index )。
6. 返回 index + cp 的 [[CodeUnitCount]] 。
22.2.7.4 GetStringIndex ( S , codePointIndex )
抽象操作 GetStringIndex 接受参数 S (一个字符串)和 codePointIndex (一个非负整数),并返回一个非负整数。它将 S
解释为 UTF-16 编码的代码点序列,如 6.1.4
所述,并返回与代码点索引 codePointIndex 对应的代码单元索引。如果不存在这样的索引,它返回 S 的长度。调用时执行以下步骤:
1. 如果 S 是空字符串,返回 0。
2. 令 len 为 S 的长度。
3. 令 codeUnitCount 为 0。
4. 令 codePointCount 为 0。
5. 重复,直到 codeUnitCount < len ,
a. 如果 codePointCount = codePointIndex ,返回
codeUnitCount 。
b. 令 cp 为 CodePointAt (S ,
codeUnitCount )。
c. 将 codeUnitCount 设置为 codeUnitCount +
cp 的 [[CodeUnitCount]] 。
d. 将 codePointCount 设置为 codePointCount +
1。
6. 返回 len 。
22.2.7.5 匹配记录
匹配记录 是一个 记录
值,用于封装正则表达式匹配或捕获的起始和结束索引。
匹配记录包含 表70 中列出的字段。
表70: 匹配记录 字段
字段名
值
含义
[[StartIndex]]
一个非负的 整数
从字符串开始算起,匹配开始的位置(包括)。
[[EndIndex]]
一个 ≥ [[StartIndex]] 的 整数
从字符串开始算起,匹配结束的位置(不包括)。
22.2.7.6 GetMatchString ( S , match )
抽象操作 GetMatchString 接受参数 S (一个字符串)和 match (一个 匹配记录 ),并返回一个字符串。调用时执行以下步骤:
1. 断言 :match .[[StartIndex]] ≤ match .[[EndIndex]] ≤
S 的长度。
2. 返回 S 从 match .[[StartIndex]] 到 match .[[EndIndex]] 的
子字符串 。
22.2.7.7 GetMatchIndexPair ( S , match )
抽象操作 GetMatchIndexPair 接受参数 S (一个字符串)和 match (一个 匹配记录 ),并返回一个数组。调用时执行以下步骤:
1. 断言 :match .[[StartIndex]] ≤ match .[[EndIndex]] ≤
S 的长度。
2. 返回 从列表创建数组 («𝔽 (match .[[StartIndex]] ), 𝔽 (match .[[EndIndex]] )»)。
22.2.7.8 MakeMatchIndicesIndexPairArray ( S , indices ,
groupNames , hasGroups )
抽象操作 MakeMatchIndicesIndexPairArray 接受参数 S (一个字符串)、indices (一个包含 匹配记录 或 undefined
的列表 )、groupNames (一个包含字符串或
undefined 的列表 )和
hasGroups (一个布尔值),并返回一个数组。调用时执行以下步骤:
1. 让 n 等于 indices 中的元素数量。
2. 断言 :n < 232 - 1。
3. 断言 :groupNames 有 n - 1
个元素。
4. 注意:groupNames 列表中的元素与 indices 列表中的元素从
indices [1] 开始对齐。
5. 令 A 为 !ArrayCreate (n )。
6. 如果 hasGroups 为 true ,则
a. 令 groups 为 OrdinaryObjectCreate (null )。
7. 否则,
a. 令 groups 为 undefined 。
8. 执行 !CreateDataPropertyOrThrow (A ,
"groups" , groups )。
9. 对于每个整数 i ,满足 0 ≤ i < n ,按升序进行,
a. 令 matchIndices 为 indices [i ]。
b. 如果 matchIndices 不是 undefined ,则
i. 令 matchIndexPair 为 GetMatchIndexPair (S ,
matchIndices )。
c. 否则,
i. 令 matchIndexPair 为
undefined 。
d. 执行 !CreateDataPropertyOrThrow (A ,
!ToString (𝔽 (i )),
matchIndexPair )。
e. 如果 i > 0 且 groupNames [i -
1] 不是 undefined ,则
i. 断言 :groups 不是
undefined 。
ii. 执行 !CreateDataPropertyOrThrow (groups ,
groupNames [i - 1], matchIndexPair )。
10. 返回 A 。
22.2.8 RegExp 实例的属性
RegExp 实例是普通对象 ,继承自RegExp
原型对象 。RegExp 实例具有内部插槽 [[OriginalSource]] 、[[OriginalFlags]] 、[[RegExpRecord]] 和 [[RegExpMatcher]] 。[[RegExpMatcher]] 内部插槽的值是 RegExp 对象模式 的抽象闭包 表示形式。
注
在 ECMAScript 2015 之前,RegExp 实例被指定为拥有 数据属性
"source" 、"global" 、"ignoreCase" 和
"multiline" 。这些属性现在被指定为 RegExp.prototype
的访问器属性 。
RegExp 实例还具有以下属性:
22.2.8.1 lastIndex
"lastIndex" 属性的值指定从哪个字符串索引开始下一次匹配。在使用时,它会被强制转换为整数 (参见22.2.7.2 )。此属性应具有以下特性:{ [[Writable]] : true , [[Enumerable]] :
false , [[Configurable]] : false }。
22.2.9 RegExp 字符串迭代器对象
RegExp 字符串迭代器是一个对象,它表示某个特定的 RegExp 实例对象与某个特定的字符串实例对象匹配时的特定迭代。RegExp 字符串迭代器对象没有命名的构造函数 。相反,RegExp 字符串迭代器对象是通过调用 RegExp
实例对象的某些方法创建的。
22.2.9.1 CreateRegExpStringIterator ( R , S ,
global , fullUnicode )
抽象操作 CreateRegExpStringIterator 接受参数 R (一个对象)、S (一个字符串)、global (一个布尔值)和
fullUnicode (一个布尔值),并返回一个生成器。调用时执行以下步骤:
1. 创建一个新的抽象闭包
closure ,没有参数,捕获 R 、S 、global 和
fullUnicode ,并在调用时执行以下步骤:
a. 重复执行以下步骤:
i. 令 match 为 ? RegExpExec (R , S )。
ii. 如果 match 为 null ,则返回
undefined 。
iii. 如果 global 为 false ,则
1. 执行 ? GeneratorYield (CreateIterResultObject (match ,
false ))。
2. 返回 undefined 。
iv. 令 matchStr 为 ? ToString (? Get (match , "0" ))。
v. 如果 matchStr 是空字符串,则
1. 令 thisIndex 为 ℝ (?
ToLength (? Get (R ,
"lastIndex" )))。
2. 令 nextIndex 为 AdvanceStringIndex (S ,
thisIndex , fullUnicode )。
3. 执行 ? Set (R , "lastIndex" ,
𝔽 (nextIndex ),
true )。
vi. 执行 ? GeneratorYield (CreateIterResultObject (match ,
false ))。
2. 返回 CreateIteratorFromClosure (closure ,
"%RegExpStringIteratorPrototype%" , %RegExpStringIteratorPrototype% )。
22.2.9.2 %RegExpStringIteratorPrototype% 对象
%RegExpStringIteratorPrototype% 对象:
22.2.9.2.1 %RegExpStringIteratorPrototype%.next ( )
1. 返回 ? GeneratorResume (this 值,
empty , "%RegExpStringIteratorPrototype%" )。
22.2.9.2.2 %RegExpStringIteratorPrototype% [ @@toStringTag ]
@@toStringTag 属性的初始值是字符串值
"RegExp String Iterator" 。
此属性的特性为 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] : true }。
23 索引集合
23.1 数组对象
数组是一种特殊对待某类属性名称的异类对象 。有关此特殊处理的定义,请参见10.4.2 。
23.1.1 数组构造函数
数组构造函数 constructor :
是 %Array% 。
是 全局对象 的 "Array"
属性的初始值。
当作 构造函数 调用时,创建并初始化一个新数组。
当作函数调用时,也会创建并初始化一个新数组,而不是作为 构造函数 。因此,函数调用 Array(…)
等同于对象创建表达式 new Array(…)
,使用相同的参数。
是一个函数,其行为根据其参数的数量和类型而异。
可以用作类定义的 extends
子句的值。意图继承异类数组行为的子类 构造函数 必须包括对数组构造函数 constructor 的 super
调用,以初始化作为
数组异类对象 的子类实例。然而,大多数
Array.prototype
方法都是通用方法,不依赖于它们的 this 值是否为 数组异类对象 。
23.1.1.1 Array ( ...values )
当调用此函数时,执行以下步骤:
1. 如果 NewTarget 是 undefined ,则将
newTarget 设为 活动函数对象 ;否则将
newTarget 设为 NewTarget。
2. 让 proto 为 ? GetPrototypeFromConstructor (newTarget ,
"%Array.prototype%" )。
3. 让 numberOfArgs 为 values 中的元素数量。
4. 如果 numberOfArgs = 0,则
a. 返回 ! ArrayCreate (0,
proto )。
5. 否则,如果 numberOfArgs = 1,则
a. 让 len 为 values [0]。
b. 让 array 为 ! ArrayCreate (0,
proto )。
c. 如果 len 不是一个 数字 ,则
i. 执行 ! CreateDataPropertyOrThrow (array ,
"0" , len )。
ii. 让 intLen 为 1 𝔽 。
d. 否则,
i. 让 intLen 为 ! ToUint32 (len )。
ii. 如果 SameValueZero (intLen ,
len ) 为 false ,则抛出一个 RangeError 异常。
e. 执行 ! Set (array ,
"length" , intLen , true )。
f. 返回 array 。
6. 否则,
a. Assert : numberOfArgs ≥
2。
b. 让 array 为 ? ArrayCreate (numberOfArgs ,
proto )。
c. 让 k 为 0。
d. 重复,当 k < numberOfArgs 时,
i. 让 Pk 为 ! ToString (𝔽 (k ))。
ii. 让 itemK 为
values [k ]。
iii. 执行 ! CreateDataPropertyOrThrow (array ,
Pk , itemK )。
iv. 将 k 设为 k + 1。
e. Assert : array 的
"length" 属性的 数学值 为
numberOfArgs 。
f. 返回 array 。
23.1.2 数组构造函数的属性
数组构造函数 constructor :
23.1.2.1 Array.from ( items [ , mapfn [ ,
thisArg ] ] )
调用此方法时执行以下步骤:
1. 让 C 为 this 值。
2. 如果 mapfn 是 undefined ,那么
a. 让 mapping 为 false 。
3. 否则,
a. 如果 IsCallable (mapfn ) 为
false ,抛出一个 TypeError 异常。
b. 让 mapping 为 true 。
4. 让 usingIterator 为 ? GetMethod (items , @@iterator )。
5. 如果 usingIterator 不为 undefined ,那么
a. 如果 IsConstructor (C )
为 true ,那么
i. 让 A 为 ? Construct (C )。
b. 否则,
i. 让 A 为 ! ArrayCreate (0)。
c. 让 iteratorRecord 为 ? GetIteratorFromMethod (items ,
usingIterator )。
d. 让 k 为 0。
e. 重复,
i. 如果 k ≥ 2** 53 - 1,那么
1. 让 error 为 ThrowCompletion (一个新创建的
TypeError 对象)。
2. 返回 ? IteratorClose (iteratorRecord ,
error )。
ii. 让 Pk 为 ! ToString (𝔽 (k ))。
iii. 让 next 为 ? IteratorStepValue (iteratorRecord )。
iv. 如果 next 是 done ,那么
1. 执行 ? Set (A , "length" ,
𝔽 (k ),
true )。
2. 返回 A 。
v. 如果 mapping 为 true ,那么
1. 让 mappedValue 为 Completion (Call (mapfn , thisArg , «
next , 𝔽 (k ) »))。
2. IfAbruptCloseIterator (mappedValue ,
iteratorRecord )。
vi. 否则,
1.
让 mappedValue 为 next 。
vii. 让 defineStatus 为 Completion (CreateDataPropertyOrThrow (A , Pk ,
mappedValue ))。
viii. IfAbruptCloseIterator (defineStatus ,
iteratorRecord )。
ix. 设置 k 为 k + 1。
6. 注意:items 不是可迭代的,所以假设它是一个 类数组对象 。
7. 让 arrayLike 为 ! ToObject (items )。
8. 让 len 为 ? LengthOfArrayLike (arrayLike )。
9. 如果 IsConstructor (C ) 为
true ,那么
a. 让 A 为 ? Construct (C , « 𝔽 (len ) »)。
10. 否则,
a. 让 A 为 ? ArrayCreate (len )。
11. 让 k 为 0。
12. 重复,当 k < len 时,
a. 让 Pk 为 ! ToString (𝔽 (k ))。
b. 让 kValue 为 ? Get (arrayLike , Pk )。
c. 如果 mapping 为 true ,那么
i. 让 mappedValue 为 ? Call (mapfn , thisArg , «
kValue , 𝔽 (k ) »)。
d. 否则,
i. 让 mappedValue 为 kValue 。
e. 执行 ? CreateDataPropertyOrThrow (A , Pk ,
mappedValue )。
f. 设置 k 为 k + 1。
13. 执行 ? Set (A , "length" , 𝔽 (len ),
true )。
14. 返回 A 。
注
此方法是一个有意通用的工厂方法;它不要求其 this 值是 Array 构造函数 。因此,它可以被传递到或继承自任何其他可以用单个数字参数调用的
构造函数 。
23.1.2.2 Array.isArray ( arg )
调用此函数时执行以下步骤:
1. 返回 ? IsArray (arg )。
23.1.2.3 Array.of ( ...items )
调用此方法时执行以下步骤:
1. 让 len 为 items 中元素的数量。
2. 让 lenNumber 为 𝔽 (len )。
3. 让 C 为 this 值。
4. 如果 IsConstructor (C ) 为
true ,那么
a. 让 A 为 ? Construct (C , « lenNumber »)。
5. 否则,
a. 让 A 为 ? ArrayCreate (len )。
6. 让 k 为 0。
7. 重复,当 k < len 时,
a. 让 kValue 为 items [k ]。
b. 让 Pk 为 ! ToString (𝔽 (k ))。
c. 执行 ? CreateDataPropertyOrThrow (A , Pk ,
kValue )。
d. 设置 k 为 k + 1。
8. 执行 ? Set (A , "length" ,
lenNumber , true )。
9. 返回 A 。
注
此方法是一个有意通用的工厂方法;它不要求其 this 值是 Array 构造函数 。因此,它可以被传递到或继承自其他可以用单个数字参数调用的
构造函数 。
23.1.2.4 Array.prototype
Array.prototype
的值是 Array
原型对象 。
此属性具有以下特性:{ [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
false }。
23.1.2.5 get Array [ @@species ]
Array[@@species]
是一个 访问器属性 ,其设置访问器函数为
undefined 。其获取访问器函数在调用时执行以下步骤:
1. 返回 this 值。
此函数的 "name" 属性的值为 "get [Symbol.species]" 。
注
Array 原型方法通常使用其 this 值的 构造函数 来创建派生对象。然而,子类 构造函数 可以通过重新定义其 @@species 属性来覆盖这种默认行为。
23.1.3 Array 原型对象的属性
Array 原型对象 :
是 %Array.prototype% 。
是一个 数组特殊对象 并具有为此类对象指定的内部方法。
具有一个 "length" 属性,其初始值为 +0 𝔽 ,其属性为 { [[Writable]] : true , [[Enumerable]] :
false , [[Configurable]] : false }。
具有一个 [[Prototype]] 内部槽,其值为 %Object.prototype% 。
注
Array 原型对象被指定为 数组特殊对象 以确保与 ECMAScript 2015
规范之前创建的 ECMAScript 代码的兼容性。
23.1.3.1 Array.prototype.at ( index )
1. 让 O 为 ? ToObject (this 值)。
2. 让 len 为 ? LengthOfArrayLike (O )。
3. 让 relativeIndex 为 ? ToIntegerOrInfinity (index )。
4. 如果 relativeIndex ≥ 0,那么
a. 让 k 为 relativeIndex 。
5. 否则,
a. 让 k 为 len + relativeIndex 。
6. 如果 k < 0 或 k ≥ len ,返回
undefined 。
7. 返回 ? Get (O ,
! ToString (𝔽 (k )))。
23.1.3.2 Array.prototype.concat ( ...items )
此方法返回一个数组,其中包含对象的数组元素,后跟每个参数的数组元素。
调用时执行以下步骤:
1. 让 O 为 ? ToObject (this 值)。
2. 让 A 为 ? ArraySpeciesCreate (O , 0)。
3. 让 n 为 0。
4. 将 O 预先添加到 items 。
5. 对 items 的每个元素 E ,执行以下步骤:
a. 让 spreadable 为 ? IsConcatSpreadable (E )。
b. 如果 spreadable 为 true ,那么
i. 让 len 为 ? LengthOfArrayLike (E )。
ii. 如果 n + len > 2** 53 - 1,抛出 TypeError 异常。
iii. 让 k 为 0。
iv. 重复,当 k < len 时,
1. 让 Pk 为 ! ToString (𝔽 (k ))。
2. 让 exists 为 ? HasProperty (E , Pk )。
3. 如果 exists 为 true ,那么
a. 让 subElement 为 ? Get (E , Pk )。
b. 执行 ? CreateDataPropertyOrThrow (A ,
! ToString (𝔽 (n )),
subElement )。
4. 设置 n 为 n + 1。
5. 设置 k 为 k + 1。
c. 否则,
i. 注意:E 作为单个项目添加,而不是展开。
ii. 如果 n ≥ 2** 53 - 1,抛出 TypeError 异常。
iii. 执行 ? CreateDataPropertyOrThrow (A ,
! ToString (𝔽 (n )),
E )。
iv. 设置 n 为 n + 1。
6. 执行 ? Set (A , "length" , 𝔽 (n ),
true )。
7. 返回 A 。
此方法的 "length" 属性为 1 𝔽 。
注 1
在步骤 6 中显式设置
"length" 属性旨在确保当 items 的最后一个非空元素具有尾部空洞或 A 不是内置数组时长度是正确的。
注 2
此方法有意是通用的;它不要求其 this 值是数组。因此,它可以被转移到其他类型的对象上用作方法。
23.1.3.2.1 IsConcatSpreadable ( O )
抽象操作 IsConcatSpreadable 接受参数 O (一个 ECMAScript
语言值 )并返回一个 正常完成记录 ,包含布尔值或一个
抛出完成记录 。调用时执行以下步骤:
1. 如果 O 不是一个对象 ,返回
false 。
2. 让 spreadable 为 ? Get (O , @@isConcatSpreadable )。
3. 如果 spreadable 不为 undefined ,返回
ToBoolean (spreadable )。
4. 返回 ? IsArray (O )。
23.1.3.3 Array.prototype.constructor
Array.prototype.constructor
的初始值是 %Array% 。
23.1.3.4 Array.prototype.copyWithin ( target , start [
, end ] )
注 1
end 参数是可选的。如果未提供,则使用 this 值的长度。
注 2
如果 target 为负数,则将其视为 length +
target ,其中 length 是数组的长度。如果 start 为负数,则将其视为 length + start 。如果 end 为负数,则将其视为 length + end 。
调用此方法时执行以下步骤:
1. 让 O 为 ? ToObject (this 值)。
2. 让 len 为 ? LengthOfArrayLike (O )。
3. 让 relativeTarget 为 ? ToIntegerOrInfinity (target )。
4. 如果 relativeTarget = -∞,让 to 为 0。
5. 否则,如果 relativeTarget < 0,让 to 为
max (len +
relativeTarget , 0)。
6. 否则,让 to 为 min (relativeTarget ,
len )。
7. 让 relativeStart 为 ? ToIntegerOrInfinity (start )。
8. 如果 relativeStart = -∞,让 from 为 0。
9. 否则,如果 relativeStart < 0,让 from 为
max (len +
relativeStart , 0)。
10. 否则,让 from 为 min (relativeStart ,
len )。
11. 如果 end 是 undefined ,让
relativeEnd 为 len ;否则让 relativeEnd 为 ? ToIntegerOrInfinity (end )。
12. 如果 relativeEnd = -∞,让 final 为 0。
13. 否则,如果 relativeEnd < 0,让 final 为
max (len +
relativeEnd , 0)。
14. 否则,让 final 为 min (relativeEnd ,
len )。
15. 让 count 为 min (final - from ,
len - to )。
16. 如果 from < to 且 to <
from + count ,则
a. 让 direction 为 -1。
b. 设置 from 为 from + count - 1。
c. 设置 to 为 to + count - 1。
17. 否则,
a. 让 direction 为 1。
18. 重复,当 count > 0 时,
a. 让 fromKey 为 ! ToString (𝔽 (from ))。
b. 让 toKey 为 ! ToString (𝔽 (to ))。
c. 让 fromPresent 为 ? HasProperty (O , fromKey )。
d. 如果 fromPresent 为 true ,则
i. 让 fromVal 为 ? Get (O , fromKey )。
ii. 执行 ? Set (O , toKey , fromVal ,
true )。
e. 否则,
i. 断言 :fromPresent 为
false 。
ii. 执行 ? DeletePropertyOrThrow (O , toKey )。
f. 设置 from 为 from + direction 。
g. 设置 to 为 to + direction 。
h. 设置 count 为 count - 1。
19. 返回 O 。
注 3
此方法有意是通用的;它不要求其 this 值是数组。因此,它可以被转移到其他类型的对象上用作方法。
23.1.3.5 Array.prototype.entries ( )
调用此方法时执行以下步骤:
1. 让 O 为 ? ToObject (this 值)。
2. 返回 CreateArrayIterator (O ,
key+value )。
23.1.3.6 Array.prototype.every ( callbackfn [ ,
thisArg ] )
注 1
callbackfn 应该是一个接受三个参数并返回一个可强制转换为布尔值的值的函数。every
按升序依次为数组中的每个元素调用
callbackfn ,直到找到一个 callbackfn 返回 false
的元素。如果找到这样的元素,every
立即返回 false 。否则,如果 callbackfn 对所有元素都返回
true ,every
将返回 true 。callbackfn
仅为数组中实际存在的元素调用;对于数组中缺失的元素不会调用。
如果提供了 thisArg 参数,它将在每次调用 callbackfn 时作为 this 值使用。如果未提供,则使用
undefined 。
callbackfn 以三个参数调用:元素的值、元素的索引和正在遍历的对象。
every
不直接改变调用它的对象,但对象可能会因对 callbackfn 的调用而发生变化。
every
处理的元素范围在第一次调用 callbackfn 之前就已确定。在 every
调用开始后添加到数组的元素不会被
callbackfn 访问。如果数组的现有元素发生变化,它们传递给 callbackfn 的值将是 every
访问它们时的值;在调用
every
开始后删除的元素在访问前不会被访问。every
类似于数学中的“对所有”量词。特别是,对于一个空数组,它返回
true 。
调用此方法时执行以下步骤:
1. 让 O 为 ? ToObject (this 值)。
2. 让 len 为 ? LengthOfArrayLike (O )。
3. 如果 IsCallable (callbackfn ) 为
false ,抛出 TypeError 异常。
4. 让 k 为 0。
5. 重复,当 k < len 时,
a. 让 Pk 为 ! ToString (𝔽 (k ))。
b. 让 kPresent 为 ? HasProperty (O , Pk )。
c. 如果 kPresent 为 true ,那么
i. 让 kValue 为 ? Get (O , Pk )。
ii. 让 testResult 为 ToBoolean (?
Call (callbackfn , thisArg , «
kValue , 𝔽 (k ),
O »))。
iii. 如果 testResult 为 false ,返回
false 。
d. 设置 k 为 k + 1。
6. 返回 true 。
注 2
此方法有意是通用的;它不要求其 this 值是数组。因此,它可以被转移到其他类型的对象上用作方法。
23.1.3.7 Array.prototype.fill ( value [ , start [ ,
end ] ] )
注 1
start 参数是可选的。如果未提供,则使用 +0 𝔽 。
end 参数是可选的。如果未提供,则使用 this 值的长度。
注 2
如果 start 为负数,则将其视为 length +
start ,其中 length 是数组的长度。如果 end 为负数,则将其视为 length + end 。
调用此方法时执行以下步骤:
1. 让 O 为 ? ToObject (this 值)。
2. 让 len 为 ? LengthOfArrayLike (O )。
3. 让 relativeStart 为 ? ToIntegerOrInfinity (start )。
4. 如果 relativeStart = -∞,让 k 为 0。
5. 否则,如果 relativeStart < 0,让 k 为 max (len +
relativeStart , 0)。
6. 否则,让 k 为 min (relativeStart ,
len )。
7. 如果 end 是 undefined ,让
relativeEnd 为 len ;否则让 relativeEnd 为 ? ToIntegerOrInfinity (end )。
8. 如果 relativeEnd = -∞,让 final 为 0。
9. 否则,如果 relativeEnd < 0,让 final 为
max (len +
relativeEnd , 0)。
10. 否则,让 final 为 min (relativeEnd ,
len )。
11. 重复,当 k < final 时,
a. 让 Pk 为 ! ToString (𝔽 (k ))。
b. 执行 ? Set (O , Pk , value ,
true )。
c. 设置 k 为 k + 1。
12. 返回 O 。
注 3
此方法有意是通用的;它不要求其 this 值是数组。因此,它可以被转移到其他类型的对象上用作方法。
23.1.3.8 Array.prototype.filter ( callbackfn [ ,
thisArg ] )
注 1
callbackfn 应该是一个接受三个参数并返回一个可强制转换为布尔值的值的函数。filter
按升序依次为数组中的每个元素调用
callbackfn ,并构建一个由 callbackfn 返回 true
的所有值的新数组。callbackfn 仅为数组中实际存在的元素调用;对于数组中缺失的元素不会调用。
如果提供了 thisArg 参数,它将在每次调用 callbackfn 时作为 this 值使用。如果未提供,则使用
undefined 。
callbackfn 以三个参数调用:元素的值、元素的索引和正在遍历的对象。
filter
不直接改变调用它的对象,但对象可能会因对 callbackfn 的调用而发生变化。
filter
处理的元素范围在第一次调用 callbackfn 之前就已确定。在 filter
调用开始后添加到数组的元素不会被
callbackfn 访问。如果数组的现有元素发生变化,它们传递给 callbackfn 的值将是 filter
访问它们时的值;在调用 filter
开始后删除的元素在访问前不会被访问。
调用此方法时执行以下步骤:
1. 让 O 为 ? ToObject (this 值)。
2. 让 len 为 ? LengthOfArrayLike (O )。
3. 如果 IsCallable (callbackfn ) 为
false ,抛出 TypeError 异常。
4. 让 A 为 ? ArraySpeciesCreate (O , 0)。
5. 让 k 为 0。
6. 让 to 为 0。
7. 重复,当 k < len 时,
a. 让 Pk 为 ! ToString (𝔽 (k ))。
b. 让 kPresent 为 ? HasProperty (O , Pk )。
c. 如果 kPresent 为 true ,那么
i. 让 kValue 为 ? Get (O , Pk )。
ii. 让 selected 为 ToBoolean (?
Call (callbackfn , thisArg , «
kValue , 𝔽 (k ),
O »))。
iii. 如果 selected 为 true ,那么
1. 执行 ? CreateDataPropertyOrThrow (A ,
! ToString (𝔽 (to )),
kValue )。
2. 设置 to 为 to + 1。
d. 设置 k 为 k + 1。
8. 返回 A 。
注 2
此方法有意是通用的;它不要求其 this 值是数组。因此,它可以被转移到其他类型的对象上用作方法。
23.1.3.9 Array.prototype.find ( predicate [ , thisArg
] )
注 1
此方法按升序索引顺序为数组的每个元素调用一次 predicate ,直到找到一个 predicate 返回一个可强制转换为
true 的值的元素。如果找到这样的元素,find
立即返回该元素值。否则,find
返回
undefined 。
有关更多信息,请参阅 FindViaPredicate 。
调用此方法时执行以下步骤:
1. 让 O 为 ? ToObject (this 值)。
2. 让 len 为 ? LengthOfArrayLike (O )。
3. 让 findRec 为 ? FindViaPredicate (O , len ,
ascending , predicate , thisArg )。
4. 返回 findRec .[[Value]] 。
注 2
此方法有意是通用的;它不要求其 this 值是数组。因此,它可以被转移到其他类型的对象上用作方法。
23.1.3.10 Array.prototype.findIndex ( predicate [ ,
thisArg ] )
注 1
此方法按升序索引顺序为数组的每个元素调用一次 predicate ,直到找到一个 predicate 返回一个可强制转换为
true 的值的元素。如果找到这样的元素,findIndex
立即返回该元素值的索引。否则,findIndex
返回 -1。
有关更多信息,请参阅 FindViaPredicate 。
调用此方法时执行以下步骤:
1. 让 O 为 ? ToObject (this 值)。
2. 让 len 为 ? LengthOfArrayLike (O )。
3. 让 findRec 为 ? FindViaPredicate (O , len ,
ascending , predicate , thisArg )。
4. 返回 findRec .[[Index]] 。
注 2
此方法有意是通用的;它不要求其 this 值是数组。因此,它可以被转移到其他类型的对象上用作方法。
23.1.3.11 Array.prototype.findLast ( predicate [ ,
thisArg ] )
注 1
此方法按降序索引顺序为数组的每个元素调用一次 predicate ,直到找到一个 predicate 返回一个可强制转换为
true 的值的元素。如果找到这样的元素,findLast
立即返回该元素值。否则,findLast
返回
undefined 。
有关更多信息,请参阅 FindViaPredicate 。
调用此方法时执行以下步骤:
1. 让 O 为 ? ToObject (this 值)。
2. 让 len 为 ? LengthOfArrayLike (O )。
3. 让 findRec 为 ? FindViaPredicate (O , len ,
descending , predicate , thisArg )。
4. 返回 findRec .[[Value]] 。
注 2
此方法有意是通用的;它不要求其 this 值是数组对象。因此,它可以被转移到其他类型的对象上用作方法。
23.1.3.12 Array.prototype.findLastIndex ( predicate [ ,
thisArg ] )
注 1
此方法按降序索引顺序为数组的每个元素调用一次 predicate ,直到找到一个 predicate 返回一个可强制转换为
true 的值的元素。如果找到这样的元素,findLastIndex
立即返回该元素值的索引。否则,findLastIndex
返回 -1。
有关更多信息,请参阅 FindViaPredicate 。
调用此方法时执行以下步骤:
1. 让 O 为 ? ToObject (this 值)。
2. 让 len 为 ? LengthOfArrayLike (O )。
3. 让 findRec 为 ? FindViaPredicate (O , len ,
descending , predicate , thisArg )。
4. 返回 findRec .[[Index]] 。
注 2
此方法有意是通用的;它不要求其 this 值是数组对象。因此,它可以被转移到其他类型的对象上用作方法。
23.1.3.12.1 FindViaPredicate ( O , len ,
direction , predicate , thisArg )
抽象操作 FindViaPredicate 接受参数
O (一个对象)、len (一个非负整数)、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 。
调用此操作时执行以下步骤:
1. 如果 IsCallable (predicate )
为 false ,则抛出一个 TypeError 异常。
2. 如果 direction 是 ascending ,则
a. 让 indices 为一个列表,包含从 0(含)到
len (不含)之间的整数,按升序排列。
3. 否则,
a. 让 indices 为一个列表,包含从 0(含)到
len (不含)之间的整数,按降序排列。
4. 对于 indices 中的每个整数 k ,执行以下操作:
a. 让 Pk 为 ! ToString (𝔽 (k )).
b. 注意:如果 O 是一个 TypedArray ,则以下对
Get 的调用将返回一个正常完成。
c. 让 kValue 为 ? Get (O , Pk )。
d. 让 testResult 为 ? Call (predicate , thisArg ,
«kValue , 𝔽 (k ),
O »)。
e. 如果 ToBoolean (testResult )
为 true ,则返回记录 { [[Index]] : 𝔽 (k ), [[Value]] : kValue }。
5. 返回记录 { [[Index]] :
-1 𝔽 , [[Value]] :
undefined }。
23.1.3.13 Array.prototype.flat ( [ depth ] )
调用此方法时执行以下步骤:
1. 让 O 为 ? ToObject (this 值)。
2. 让 sourceLen 为 ? LengthOfArrayLike (O )。
3. 令 depthNum 为 1。
4. 如果 depth 不是 undefined ,则
a. 将 depthNum 设置为 ? ToIntegerOrInfinity (depth )。
b. 如果 depthNum 小于 0,则将 depthNum 设置为 0。
5. 让 A 为 ? ArraySpeciesCreate (O , 0)。
6. 执行 ? FlattenIntoArray (A , O ,
sourceLen , 0, depthNum )。
7. 返回 A 。
23.1.3.13.1 FlattenIntoArray ( target , source ,
sourceLen , start , depth [ , mapperFunction [ ,
thisArg ] ] )
抽象操作 FlattenIntoArray 接受参数
target (一个对象)、source (一个对象)、sourceLen (一个非负整数)、start (一个非负整数)和
depth (一个非负整数或 +∞),以及可选参数 mapperFunction (一个函数对象)和 thisArg (一个 ECMAScript
语言值),并返回一个包含非负整数的正常完成记录或一个抛出完成记录。调用时执行以下步骤:
1. 断言 :如果 mapperFunction 存在,则
IsCallable (mapperFunction )
为 true ,thisArg 存在,且 depth 为 1。
2. 令 targetIndex 为 start 。
3. 令 sourceIndex 为 +0 𝔽 。
4. 重复以下步骤,直到 ℝ (sourceIndex ) <
sourceLen ,
a. 让 P 为 ! ToString (sourceIndex )。
b. 让 exists 为 ? HasProperty (source , P )。
c. 如果 exists 为 true ,则
i. 让 element 为 ? Get (source , P )。
ii. 如果 mapperFunction 存在,则
1. 将 element 设置为 ? Call (mapperFunction ,
thisArg , « element , sourceIndex ,
source »)。
iii. 令 shouldFlatten 为
false 。
iv. 如果 depth > 0,则
1. 将 shouldFlatten 设置为 ? IsArray (element )。
v. 如果 shouldFlatten 为 true ,则
1. 如果 depth = +∞,则令 newDepth 为
+∞。
2. 否则,令 newDepth 为 depth - 1。
3. 令 element
Len 为 ? LengthOfArrayLike (element )。
4. 将 targetIndex 设置为 ? FlattenIntoArray (target ,
element , elementLen , targetIndex , newDepth )。
vi. 否则,
1. 如果 targetIndex ≥ 253 - 1,抛出一个
TypeError 异常。
2. 执行 ? CreateDataPropertyOrThrow (target ,
! ToString (𝔽 (targetIndex )),
element )。
3. 将 targetIndex 设置为 targetIndex
+ 1。
d. 将 sourceIndex 设置为 sourceIndex +
1 𝔽 。
5. 返回 targetIndex 。
23.1.3.14 Array.prototype.flatMap ( mapperFunction [ ,
thisArg ] )
调用此方法时执行以下步骤:
1. 让 O 为 ? ToObject (this 值)。
2. 让 sourceLen 为 ? LengthOfArrayLike (O )。
3. 如果 IsCallable (mapperFunction )
为 false ,则抛出一个 TypeError 异常。
4. 让 A 为 ? ArraySpeciesCreate (O , 0)。
5. 执行 ? FlattenIntoArray (A , O ,
sourceLen , 0, 1, mapperFunction , thisArg )。
6. 返回 A 。
23.1.3.15 Array.prototype.forEach ( callbackfn [ ,
thisArg ] )
注 1
callbackfn 应该是一个接受三个参数的函数。forEach
会为数组中存在的每个元素调用一次
callbackfn ,按升序调用。callbackfn 只会被调用数组中实际存在的元素;对于数组中缺失的元素不会调用。
如果提供了 thisArg 参数,它将在每次调用 callbackfn 时作为 this 值使用。如果未提供,则使用
undefined 。
callbackfn 被调用时传递三个参数:元素的值、元素的索引和被遍历的对象。
forEach
不会直接改变调用它的对象,但对象可能会被 callbackfn 的调用改变。
forEach
处理的元素范围在首次调用 callbackfn 前设置。在调用 forEach
开始后追加到数组的元素不会被
callbackfn 访问。如果数组中的现有元素被更改,它们在 forEach
访问它们时的值将是 callbackfn
访问它们时的值;在调用 forEach
开始后且在访问之前被删除的元素不会被访问。
调用此方法时执行以下步骤:
1. 令 O 为 ? ToObject (this 值)。
2. 令 len 为 ? LengthOfArrayLike (O )。
3. 如果 IsCallable (callbackfn ) 为
false ,则抛出一个 TypeError 异常。
4. 令 k 为 0。
5. 重复,直到 k < len ,
a. 令 Pk 为 ! ToString (𝔽 (k ))。
b. 令 kPresent 为 ? HasProperty (O , Pk )。
c. 如果 kPresent 为 true ,则
i. 令 kValue 为 ? Get (O , Pk )。
ii. 执行 ? Call (callbackfn , thisArg , «
kValue , 𝔽 (k ),
O »)。
d. 将 k 设为 k + 1。
6. 返回 undefined 。
注 2
此方法是有意泛化的;它不要求其 this 值为一个数组。因此,它可以转移到其他类型的对象上作为方法使用。
23.1.3.16 Array.prototype.includes ( searchElement [ ,
fromIndex ] )
注 1
此方法使用 SameValueZero 算法按升序将
searchElement 与数组的元素进行比较,如果在任何位置找到,返回 true ;否则,返回
false 。
可选的第二个参数 fromIndex 默认值为 +0 𝔽 (即搜索整个数组)。如果它大于或等于数组的长度,则返回
false ,即不会搜索数组。如果它小于 -0 𝔽 ,则将其作为从数组末尾开始计算的偏移量来计算
fromIndex 。如果计算的索引小于或等于 +0 𝔽 ,则搜索整个数组。
调用此方法时执行以下步骤:
1. 令 O 为 ? ToObject (this 值)。
2. 令 len 为 ? LengthOfArrayLike (O )。
3. 如果 len = 0,返回 false 。
4. 令 n 为 ? ToIntegerOrInfinity (fromIndex )。
5. 断言 :如果 fromIndex 是
undefined ,则 n 为 0。
6. 如果 n = +∞,返回 false 。
7. 否则,如果 n = -∞,将 n 设为 0。
8. 如果 n ≥ 0,则
a. 令 k 为 n 。
9. 否则,
a. 令 k 为 len + n 。
b. 如果 k < 0,将 k 设为 0。
10. 重复,直到 k < len ,
a. 令 elementK 为 ? Get (O , ! ToString (𝔽 (k )))。
b. 如果 SameValueZero (searchElement ,
elementK ) 为 true ,返回 true 。
c. 将 k 设为 k + 1。
11. 返回 false 。
注 2
此方法是有意泛化的;它不要求其 this 值为一个数组。因此,它可以转移到其他类型的对象上作为方法使用。
注 3
此方法有意与类似的 indexOf
方法在两个方面不同。首先,它使用 SameValueZero 算法,而不是 IsStrictlyEqual ,使其能够检测
NaN 数组元素。其次,它不会跳过缺失的数组元素,而是将它们视为 undefined 。
23.1.3.17 Array.prototype.indexOf ( searchElement [ ,
fromIndex ] )
此方法使用 IsStrictlyEqual 算法按升序将
searchElement 与数组的元素进行比较,如果在一个或多个索引处找到,返回最小的索引;否则,返回 -1 𝔽 。
注 1
可选的第二个参数 fromIndex 默认值为 +0 𝔽 (即搜索整个数组)。如果它大于或等于数组的长度,则返回
-1 𝔽 ,即不会搜索数组。如果它小于
-0 𝔽 ,则将其作为从数组末尾开始计算的偏移量来计算 fromIndex 。如果计算的索引小于或等于
+0 𝔽 ,则搜索整个数组。
调用此方法时执行以下步骤:
1. 令 O 为 ? ToObject (this 值)。
2. 令 len 为 ? LengthOfArrayLike (O )。
3. 如果 len = 0,返回 -1 𝔽 。
4. 令 n 为 ? ToIntegerOrInfinity (fromIndex )。
5. 断言 :如果 fromIndex 是
undefined ,则 n 为 0。
6. 如果 n = +∞,返回 -1 𝔽 。
7. 否则,如果 n = -∞,将 n 设为 0。
8. 如果 n ≥ 0,则
a. 令 k 为 n 。
9. 否则,
a. 令 k 为 len + n 。
b. 如果 k < 0,将 k 设为 0。
10. 重复,直到 k < len ,
a. 令 kPresent 为 ? HasProperty (O , ! ToString (𝔽 (k )))。
b. 如果 kPresent 是 true ,则
i. 令 elementK 为 ? Get (O , ! ToString (𝔽 (k )))。
ii. 如果 IsStrictlyEqual (searchElement ,
elementK ) 为 true ,返回 𝔽 (k )。
c. 将 k 设为 k + 1。
11. 返回 -1 𝔽 。
注 2
此方法是有意泛化的;它不要求其 this 值为一个数组。因此,它可以转移到其他类型的对象上作为方法使用。
23.1.3.18 Array.prototype.join ( separator )
此方法将数组的元素转换为字符串,然后将这些字符串连接起来,以 separator 为分隔符。如果未提供分隔符,则使用单个逗号作为分隔符。
调用此方法时执行以下步骤:
1. 令 O 为 ? ToObject (this 值)。
2. 令 len 为 ? LengthOfArrayLike (O )。
3. 如果 separator 是 undefined ,则将
sep 设为 "," 。
4. 否则,将 sep 设为 ? ToString (separator )。
5. 令 R 为空字符串。
6. 令 k 为 0。
7. 重复,直到 k < len ,
a. 如果 k > 0,将 R 设为 R 和
sep 的 字符串连接 。
b. 令 element 为 ? Get (O , ! ToString (𝔽 (k )))。
c. 如果 element 是 undefined 或
null ,则将 next 设为空字符串;否则,将 next 设为 ? ToString (element )。
d. 将 R 设为 R 和 next 的 字符串连接 。
e. 将 k 设为 k + 1。
8. 返回 R 。
注
此方法是有意泛化的;它不要求其 this 值为一个数组。因此,它可以转移到其他类型的对象上作为方法使用。
23.1.3.19 Array.prototype.keys ( )
调用此方法时执行以下步骤:
1. 令 O 为 ? ToObject (this 值)。
2. 返回 CreateArrayIterator (O ,
key )。
23.1.3.20 Array.prototype.lastIndexOf ( searchElement [ ,
fromIndex ] )
注 1
此方法使用 IsStrictlyEqual 算法,将
searchElement 与数组元素进行降序比较,如果在一个或多个索引处找到,则返回最大的此类索引;否则,返回
-1 𝔽 。
可选的第二个参数 fromIndex 默认为数组的长度减去一(即搜索整个数组)。如果它大于或等于数组的长度,将搜索整个数组。如果它小于
-0 𝔽 ,则将其作为从数组末尾计算 fromIndex 的偏移量。如果计算出的索引小于或等于
+0 𝔽 ,则返回 -1 𝔽 。
调用此方法时执行以下步骤:
1. 令 O 为 ? ToObject (this 值)。
2. 令 len 为 ? LengthOfArrayLike (O )。
3. 如果 len = 0,则返回 -1 𝔽 。
4. 如果存在 fromIndex ,则令 n 为 ? ToIntegerOrInfinity (fromIndex );否则令 n 为
len - 1。
5. 如果 n = -∞,则返回 -1 𝔽 。
6. 如果 n ≥ 0,则
a. 令 k 为 min (n , len - 1)。
7. 否则,
a. 令 k 为 len + n 。
8. 重复,直到 k ≥ 0,
a. 令 kPresent 为 ? HasProperty (O , ! ToString (𝔽 (k )))。
b. 如果 kPresent 是 true ,则
i. 令 elementK 为 ? Get (O , ! ToString (𝔽 (k )))。
ii. 如果 IsStrictlyEqual (searchElement ,
elementK ) 是 true ,则返回 𝔽 (k )。
c. 令 k 为 k - 1。
9. 返回 -1 𝔽 。
注 2
此方法是故意通用的;它不要求其 this 值是数组。因此,它可以被转移到其他种类的对象中作为方法使用。
23.1.3.21 Array.prototype.map ( callbackfn [ , thisArg
] )
注 1
callbackfn 应是一个接受三个参数的函数。map
按升序依次调用
callbackfn ,并从结果中构建一个新的数组。callbackfn 只对数组中实际存在的元素调用,不对数组中缺失的元素调用。
如果提供了 thisArg 参数,则将在每次调用 callbackfn 时使用它作为 this 值。如果未提供,则使用
undefined 。
callbackfn 调用时会接受三个参数:元素的值、元素的索引和被遍历的对象。
map
不会直接改变调用它的对象,但该对象可能会被 callbackfn 的调用所改变。
map
处理的元素范围在第一次调用 callbackfn 之前确定。在调用 map
之后添加到数组中的元素不会被
callbackfn 访问。如果数组中的现有元素发生更改,它们在 callbackfn 访问时的值将是 map
访问它们时的值;在调用
map
之后并在访问之前删除的元素不会被访问。
调用此方法时执行以下步骤:
1. 令 O 为 ? ToObject (this 值)。
2. 令 len 为 ? LengthOfArrayLike (O )。
3. 如果 IsCallable (callbackfn ) 为
false ,则抛出 TypeError 异常。
4. 令 A 为 ? ArraySpeciesCreate (O , len )。
5. 令 k 为 0。
6. 重复,直到 k < len ,
a. 令 Pk 为 ! ToString (𝔽 (k ))。
b. 令 kPresent 为 ? HasProperty (O , Pk )。
c. 如果 kPresent 为 true ,则
i. 令 kValue 为 ? Get (O , Pk )。
ii. 令 mappedValue 为 ? Call (callbackfn , thisArg , «
kValue , 𝔽 (k ),
O »)。
iii. 执行 ? CreateDataPropertyOrThrow (A , Pk ,
mappedValue )。
d. 将 k 设为 k + 1。
7. 返回 A 。
注 2
此方法是故意通用的;它不要求其 this 值是数组。因此,它可以被转移到其他种类的对象中作为方法使用。
23.1.3.22 Array.prototype.pop ( )
注 1
调用此方法时执行以下步骤:
1. 令 O 为 ? ToObject (this 值)。
2. 令 len 为 ? LengthOfArrayLike (O )。
3. 如果 len = 0,则
a. 执行 ? Set (O , "length" ,
+0 𝔽 , true )。
b. 返回 undefined 。
4. 否则,
a. 断言 : len > 0。
b. 令 newLen 为 𝔽 (len - 1)。
c. 令 index 为 ! ToString (newLen )。
d. 令 element 为 ? Get (O , index )。
e. 执行 ? DeletePropertyOrThrow (O , index )。
f. 执行 ? Set (O , "length" ,
newLen , true )。
g. 返回 element 。
注 2
此方法是故意通用的;它不要求其 this 值是数组。因此,它可以被转移到其他种类的对象中作为方法使用。
23.1.3.23 Array.prototype.push ( ...items )
注 1
此方法将参数按出现顺序追加到数组的末尾。它返回数组的新长度。
调用此方法时执行以下步骤:
1. 令 O 为 ? ToObject (this 值)。
2. 令 len 为 ? LengthOfArrayLike (O )。
3. 令 argCount 为 items 中元素的数量。
4. 如果 len + argCount > 2** 53 - 1,则抛出 TypeError 异常。
5. 对于 items 中的每个元素 E ,执行以下操作:
a. 执行 ? Set (O , ! ToString (𝔽 (len )),
E , true )。
b. 将 len 设置为 len + 1。
6. 执行 ? Set (O , "length" , 𝔽 (len ),
true )。
7. 返回 𝔽 (len )。
此方法的 "length" 属性为 1 𝔽 。
注 2
此方法是故意通用的;它不要求其 this 值是数组。因此,它可以被转移到其他种类的对象中作为方法使用。
23.1.3.24 Array.prototype.reduce ( callbackfn [ ,
initialValue ] )
注 1
callbackfn 应该是一个接受四个参数的函数。reduce
按升序依次调用 callbackfn ,从数组的第一个元素开始。
callbackfn 用四个参数调用:previousValue (来自前一次 callbackfn
调用的值),currentValue (当前元素的值),currentIndex ,以及被遍历的对象。第一次调用 callbackfn
时,previousValue 和 currentValue 可能有两种值。如果在调用 reduce
时提供了
initialValue ,那么 previousValue 将是 initialValue ,而
currentValue 将是数组的第一个值。如果没有提供 initialValue ,那么 previousValue
将是数组的第一个值,currentValue 将是第二个值。如果数组为空且未提供 initialValue ,将抛出
TypeError 。
reduce
不直接改变调用它的对象,但该对象可能会被 callbackfn 的调用所修改。
reduce
处理的元素范围在第一次调用 callbackfn 之前确定。在调用 reduce
开始后添加到数组中的元素不会被
callbackfn 访问。如果在调用 reduce
期间更改了现有元素,则传递给 callbackfn 的值将是
reduce
访问它们时的值;在调用 reduce
开始后删除的元素且未被访问的元素不会被访问。
调用此方法时执行以下步骤:
1. 令 O 为 ? ToObject (this 值)。
2. 令 len 为 ? LengthOfArrayLike (O )。
3. 如果 IsCallable (callbackfn ) 是
false ,则抛出 TypeError 异常。
4. 如果 len 为 0 且未提供 initialValue ,则抛出
TypeError 异常。
5. 令 k 为 0。
6. 令 accumulator 为 undefined 。
7. 如果提供了 initialValue ,则
a. 将 accumulator 设置为 initialValue 。
8. 否则,
a. 令 kPresent 为 false 。
b. 重复,直到 kPresent 为 false 且
k 小于 len ,
i. 令 Pk 为 ! ToString (𝔽 (k ))。
ii. 将 kPresent 设置为 ? HasProperty (O , Pk )。
iii. 如果 kPresent 是 true ,则
1. 将 accumulator 设置为 ? Get (O , Pk )。
iv. 将 k 设置为 k + 1。
c. 如果 kPresent 是 false ,则抛出
TypeError 异常。
9. 重复,直到 k 小于 len ,
a. 令 Pk 为 ! ToString (𝔽 (k ))。
b. 令 kPresent 为 ? HasProperty (O , Pk )。
c. 如果 kPresent 是 true ,则
i. 令 kValue 为 ? Get (O , Pk )。 li>
ii. 将 accumulator 设置为 ? Call (callbackfn ,
undefined , « accumulator , kValue , 𝔽 (k ),
O »)。
d. 将 k 设置为 k + 1。
10. 返回 accumulator 。
注 2
此方法是故意通用的;它不要求其 this 值是数组。因此,它可以被转移到其他种类的对象中作为方法使用。
23.1.3.25 Array.prototype.reduceRight ( callbackfn [ ,
initialValue ] )
注 1
callbackfn 应该是一个接受四个参数的函数。reduceRight
以降序遍历数组中每个元素,从第二个元素开始,依次调用
callbackfn 。
callbackfn 用四个参数调用:previousValue (来自前一次 callbackfn
调用的值),currentValue (当前元素的值),currentIndex ,以及被遍历的对象。第一次调用 callbackfn
时,previousValue 和 currentValue 可能有两种值。如果在调用 reduceRight
时提供了
initialValue ,那么 previousValue 将是 initialValue ,而
currentValue 将是数组的最后一个值。如果没有提供 initialValue ,那么 previousValue
将是数组的最后一个值,currentValue 将是倒数第二个值。如果数组为空且未提供 initialValue ,将抛出
TypeError 。
reduceRight
不直接改变调用它的对象,但该对象可能会被 callbackfn 的调用所修改。
reduceRight
处理的元素范围在第一次调用 callbackfn 之前确定。在调用 reduceRight
开始后添加到数组中的元素不会被 callbackfn 访问。如果在调用 reduceRight
期间更改了现有元素,则传递给
callbackfn 的值将是 reduceRight
访问它们时的值;在调用 reduceRight
开始后删除的元素且未被访问的元素不会被访问。
调用此方法时执行以下步骤:
1. 令 O 为 ? ToObject (this 值)。
2. 令 len 为 ? LengthOfArrayLike (O )。
3. 如果 IsCallable (callbackfn ) 是
false ,则抛出 TypeError 异常。
4. 如果 len 为 0 且未提供 initialValue ,则抛出
TypeError 异常。
5. 令 k 为 len - 1。
6. 令 accumulator 为 undefined 。
7. 如果提供了 initialValue ,则
a. 将 accumulator 设置为 initialValue 。
8. 否则,
a. 令 kPresent 为 false 。
b. 重复,直到 kPresent 为 false 且
k 大于等于 0,
i. 令 Pk 为 ! ToString (𝔽 (k ))。
ii. 将 kPresent 设置为 ? HasProperty (O , Pk )。
iii. 如果 kPresent 是 true ,则
1. 将 accumulator 设置为 ? Get (O , Pk )。
iv. 将 k 设置为 k - 1。
c. 如果 kPresent 是 false ,则抛出
TypeError 异常。
9. 重复,直到 k 大于等于 0,
a. 令 Pk 为 ! ToString (𝔽 (k ))。
b. 令 kPresent 为 ? HasProperty (O , Pk )。
c. 如果 kPresent 是 true ,则
i. 令 kValue 为 ? Get
emu-xref>(O , Pk )。
ii. 将 accumulator 设置为 ? Call (callbackfn ,
undefined , « accumulator , kValue , 𝔽 (k ),
O »)。
d. 将 k 设置为 k - 1。
10. 返回 accumulator 。
注 2
此方法故意设计得很通用;它不要求其 this 值是数组。因此,它可以被转移到其他类型的对象中作为方法使用。
23.1.3.26 Array.prototype.reverse ( )
注 1
此方法重新排列数组中的元素,以反转其顺序。它返回作为调用结果的对象。
调用此方法时执行以下步骤:
1. 令 O 为 ? ToObject (this 值)。
2. 令 len 为 ? LengthOfArrayLike (O )。
3. 令 middle 为 floor (len / 2)。
4. 令 lower 为 0。
5. 重复,直到 lower ≠ middle ,
a. 令 upper 为 len - lower - 1。
b. 令 upperP 为 ! ToString (𝔽 (upper ))。
c. 令 lowerP 为 ! ToString (𝔽 (lower ))。
d. 令 lowerExists 为 ? HasProperty (O , lowerP )。
e. 如果 lowerExists 是 true ,则
i. 令 lowerValue 为 ? Get (O , lowerP )。
f. 令 upperExists 为 ? HasProperty (O , upperP )。
g. 如果 upperExists 是 true ,则
i. 令 upperValue 为 ? Get (O , upperP )。
h. 如果 lowerExists 是 true 且
upperExists 是 true ,则
i. 执行 ? Set (O , lowerP ,
upperValue , true )。
ii. 执行 ? Set (O , upperP ,
lowerValue , true )。
i. 否则,如果 lowerExists 是 false 且
upperExists 是 true ,则
i. 执行 ? Set (O , lowerP ,
upperValue , true )。
ii. 执行 ? DeletePropertyOrThrow (O , upperP )。
j. 否则,如果 lowerExists 是 true 且
upperExists 是 false ,则
i. 执行 ? DeletePropertyOrThrow (O , lowerP )。
ii. 执行 ? Set (O , upperP ,
lowerValue , true )。
k. 否则,
i. Assert :lowerExists 和
upperExists 都是 false 。
ii. 注:不需要执行任何操作。
l. 将 lower 设为 lower + 1。
6. 返回 O 。
注 2
此方法故意设计得很通用;它不要求其 this 值是数组。因此,它可以被转移到其他类型的对象中作为方法使用。
23.1.3.27 Array.prototype.shift ( )
此方法移除数组中的第一个元素并返回它。
调用此方法时执行以下步骤:
1. 令 O 为 ? ToObject (this 值)。
2. 令 len 为 ? LengthOfArrayLike (O )。
3. 如果 len = 0,则
a. 执行 ? Set (O , "length" ,
+0 𝔽 , true )。
b. 返回 undefined 。
4. 令 first 为 ? Get (O , "0" )。
5. 令 k 为 1。
6. 重复,直到 k < len ,
a. 令 from 为 ! ToString (𝔽 (k ))。
b. 令 to 为 ! ToString (𝔽 (k
- 1))。
c. 令 fromPresent 为 ? HasProperty (O , from )。
d. 如果 fromPresent 是 true ,则
i. 令 fromVal 为 ? Get (O , from )。
ii. 执行 ? Set (O , to , fromVal ,
true )。
e. 否则,
i. Assert :fromPresent 是
false 。
ii. 执行 ? DeletePropertyOrThrow (O , to )。
f. 将 k 设为 k + 1。
7. 执行 ? DeletePropertyOrThrow (O , ! ToString (𝔽 (len -
1)))。
8. 执行 ? Set (O , "length" , 𝔽 (len - 1),
true )。
9. 返回 first 。
注
此方法故意设计得很通用;它不要求其 this 值是数组。因此,它可以被转移到其他类型的对象中作为方法使用。
23.1.3.28 Array.prototype.slice ( start , end )
此方法返回一个数组,该数组包含从元素 start 开始到元素 end 之前的所有元素(如果 end 是
undefined ,则包含到数组的结尾)。如果 start 是负数,它被视为 length + start ,其中 length 是数组的长度。如果
end 是负数,它被视为 length + end ,其中
length 是数组的长度。
调用时执行以下步骤:
1. 让 O 为 ? ToObject (this
值)。
2. 让 len 为 ? LengthOfArrayLike (O ).
3. 让 relativeStart 为 ? ToIntegerOrInfinity (start ).
4. 如果 relativeStart = -∞,则让 k 为 0。
5. 否则,如果 relativeStart < 0,则让 k 为
max (len +
relativeStart , 0).
6. 否则,让 k 为 min (relativeStart ,
len ).
7. 如果 end 是 undefined ,让
relativeEnd 为 len ;否则,让 relativeEnd 为 ? ToIntegerOrInfinity (end ).
8. 如果 relativeEnd = -∞,则让 final 为 0。
9. 否则,如果 relativeEnd < 0,则让 final
为
max (len +
relativeEnd , 0).
10. 否则,让 final 为 min (relativeEnd ,
len ).
11. 让 count 为 max (final
-
k ,
0).
12. 让 A 为 ? ArraySpeciesCreate (O , count ).
13. 让 n 为 0。
14. 重复,直到 k < final ,
a. 让 Pk 为 ! ToString (𝔽 (k )).
b. 让 kPresent 为 ? HasProperty (O , Pk ).
c. 如果 kPresent 为 true ,则
i. 让 kValue 为 ? Get (O , Pk ).
ii. 执行 ? CreateDataPropertyOrThrow (A ,
! ToString (𝔽 (n )),
kValue ).
d. 将 k 增加 1。
e. 将 n 增加 1。
15. 执行
? Set (A , "length" , 𝔽 (n ),
true ).
16. 返回 A 。
注 1
步骤 15 中明确设置
"length" 属性的目的是确保长度正确,即使 A 不是内建的 Array。
注 2
此方法有意设计为通用的;它不要求其 this 值必须是 Array。因此,它可以转移到其他类型的对象中作为方法使用。
23.1.3.29 Array.prototype.some ( callbackfn [ ,
thisArg ] )
注 1
callbackfn 应该是一个接受三个参数并返回一个可以转换为布尔值的值的函数。some
会对数组中的每一个元素按升序调用
callbackfn ,直到找到一个使 callbackfn 返回 true
的元素。如果找到了这样的元素,some
会立即返回 true 。否则,some
返回
false 。callbackfn 只会被调用数组中实际存在的元素;不会对数组中的缺失元素进行调用。
如果提供了 thisArg 参数,它将作为每次调用 callbackfn 的 this
值。如果没有提供,undefined 将被用作 this 值。
callbackfn 被调用时会接收三个参数:元素的值、元素的索引和正在遍历的对象。
some
不会直接修改它被调用的对象,但对象可能会被 callbackfn 的调用所修改。
some
处理的元素范围在第一次调用 callbackfn 之前设定。调用 some
后添加到数组中的元素不会被
callbackfn 访问。如果数组中已有的元素被修改,传递给 callbackfn 的值将是 some
访问它们时的值;在
some
调用开始后被删除的元素不会被访问。some
类似于数学中的 "存在" 量词。特别地,对于一个空数组,它返回
false 。
此方法在调用时执行以下步骤:
1. 让 O 为 ? ToObject (this
值)。
2. 让 len 为 ? LengthOfArrayLike (O ).
3. 如果 ? IsCallable (callbackfn )
为 false ,抛出 TypeError 异常。
4. 让 k 为 0。
5. 重复,直到 k < len ,
a. 让 Pk 为 ! ToString (𝔽 (k )).
b. 让 kPresent 为 ? HasProperty (O , Pk ).
c. 如果 kPresent 为 true ,则
i. 让 kValue 为 ? Get (O , Pk ).
ii. 让 testResult 为 ? ToBoolean (?
Call (callbackfn , thisArg , «
kValue , 𝔽 (k ),
O »)).
iii. 如果 testResult 为
true ,则返回 true 。
d. 将 k 设为 k + 1。
6. 返回 false 。
注 2
此方法有意设计为通用的;它不要求其 this 值必须是 Array。因此,它可以转移到其他类型的对象中作为方法使用。
23.1.3.30 Array.prototype.sort ( comparefn )
此方法对数组的元素进行排序。排序必须是稳定的(即,比较相等的元素必须保持原来的顺序)。如果 comparefn 不是
undefined ,
它应该是一个接受两个参数 x 和 y 的函数,并返回一个负数
如果 x < y ,一个正数如果 x > y ,或者
零
否则。
调用时执行以下步骤:
1. 如果 comparefn 不是
undefined 并且 IsCallable (comparefn )
为 false ,抛出 TypeError 异常。
2. 设 obj 为 ? ToObject (this
值)。
3. 设 len 为
? LengthOfArrayLike (obj ).
4. 设 SortCompare 为一个新的 Abstract Closure ,具有
参数 (x , y ),捕获 comparefn 并在调用时执行以下步骤:
a. 返回 ? CompareArrayElements (x ,
y , comparefn ).
5. 设
sortedList
为 ? SortIndexedProperties (obj , len ,
SortCompare , skip-holes ).
6. 设 itemCount 为 sortedList 中的元素数量。
7. 设 j 为 0。
8. 重复,直到 j < itemCount ,
a. 执行 ? Set (obj , ! ToString (𝔽 (j )),
sortedList [j ], true ).
b. 将 j 设为 j + 1。
9. 注意:步骤 SortIndexedProperties
中调用 skip-holes 。剩余的索引将被删除,以保持检测到并排除的孔的数量。
10. 重复,直到 j < len ,
a. 执行 ? DeletePropertyOrThrow (obj , ! ToString (𝔽 (j ))).
b. 将 j 设为 j + 1。
11. 返回 obj 。
注 1
由于不存在的属性值总是比 undefined 属性值大,而 undefined 总是比任何其他值大
(见
CompareArrayElements ),
undefined 属性值总是排在结果的末尾,之后是不存在的属性值。
注 2
在步骤 ToString 抽象操作
中执行的调用可能导致 SortCompare 不作为一个 一致的比较器 行为。
注 3
此方法有意地是通用的;它不要求其 this 值必须是数组。因此,可以将其转移到其他类型的对象中使用作为方法。
23.1.3.30.1 排序索引属性 ( obj , len ,
SortCompare , holes )
抽象操作 SortIndexedProperties 接受以下参数:obj (一个对象)、len (一个非负的 整数 )、SortCompare (一个 抽象闭包 ,有两个参数),以及
holes (skip-holes 或 read-through-holes ),并返回一个
正常完成 ,其中包含一个
列表 的
ECMAScript 语言值 ,或者一个
抛出完成 。当调用时,它执行以下步骤:
1. 让 items 成为一个新的空 列表 。
2. 让 k 等于 0。
3. 重复,直到 k < len ,
a. 让 Pk 等于 ! ToString (𝔽 (k ))。
b. 如果 holes 是
skip-holes ,则
i. 让 kRead 等于 ? HasProperty (obj , Pk )。
c. 否则,
i. 断言 :holes 是
read-through-holes 。
ii. 让 kRead 等于 true 。
d. 如果 kRead 是 true ,则
i. 让 kValue 等于 ? Get (obj , Pk )。
ii. 将 kValue 添加到 items 中。
e. 将 k 设置为 k + 1。
4. 使用 实现定义的
顺序对 items 进行排序,通过一系列 对 SortCompare
的调用 。如果任何此类调用返回 突发完成 ,在执行任何进一步的
SortCompare 调用之前停止,并返回该 完成记录 。
5. 返回 items 。
排序顺序 是在完成上述算法的第 4 步骤后
items 的排列顺序。排序顺序 如果 SortCompare 不是
一致的比较器 ,则为 实现定义的 。当
SortIndexedProperties 被 Array.prototype.sort
调用时,排序顺序 也是 实现定义的 ,如果 comparefn
是 undefined ,并且对任何传递给 SortCompare 的特定值的所有 ToString 调用产生的结果不一致。
除非 排序顺序 被指定为 实现定义的 ,否则它必须满足以下所有条件:
必须存在一个非负整数的数学排列 π,小于 itemCount ,使得对于每个非负整数 j
小于 itemCount ,元素 old[j ] 与 new[π(j )] 完全相同。
对于所有非负整数 j 和 k ,它们都小于 itemCount ,如果 ℝ (SortCompare (old[j ],
old[k ])) < 0 ,则 π(j ) <
π(k ) 。
这里,符号 old[j ] 用于表示在执行步骤 4 之前的 items [j ] ,
符号 new[j ] 用于表示在执行步骤 4 之后的 items [j ] 。
如果一个抽象闭包或函数 comparator 对于一组值 S 满足以下所有要求,则它是该组值的 一致的比较器 :对所有值 a 、b 和 c (可能是相同的值)在集合 S 中:
符号 a <C b 表示 ℝ (comparator (a ,
b )) < 0 ;a =C
b 表示 ℝ (comparator (a ,
b )) = 0 ;a >C
b 表示 ℝ (comparator (a ,
b )) > 0 。
调用 comparator (a , b ) 时,对于给定的特定值对 a 和 b ,始终返回相同的值
v 。此外,v 是一个数字 ,并且
v 不是 NaN 。这意味着对于给定的 a 和 b ,a
<C b 、a =C b 和 a >C
b 中正好有一个为真。
调用 comparator (a , b ) 不会修改 obj 或 obj 的任何原型链上的对象。
a =C a (自反性)
如果 a =C b ,那么 b =C a (对称性)
如果 a =C b 且 b =C c ,那么 a
=C c (=C 的传递性)
如果 a <C b 且 b <C c ,那么
a <C c (<C 的传递性)
如果 a >C b 且 b >C c ,那么
a >C c (>C 的传递性)
注
上述条件是确保 comparator 将集合 S 划分为同值类,并且这些同值类是完全有序的的必要且充分条件。
23.1.3.30.2 CompareArrayElements ( x , y ,
comparefn )
抽象操作 CompareArrayElements 接受参数 x (一个 ECMAScript
语言值 )、y (一个 ECMAScript
语言值 )和 comparefn (一个 函数对象 或
undefined ),并返回一个 正常完成
的数字,或一个 突然完成 。调用时,它执行以下步骤:
1. 如果 x 和 y 都是
undefined ,返回 +0 𝔽 。
2. 如果 x 是 undefined ,返回
1 𝔽 。
3. 如果 y 是 undefined ,返回
-1 𝔽 。
4. 如果 comparefn 不是 undefined ,
则
a. 让 v 为 ? ToNumber (? Call (comparefn ,
undefined ,
« x , y »)).
b. 如果 v 是 NaN ,返回
+0 𝔽 。
c. 返回 v 。
5. 让 xString 为
? ToString (x )。
6. 让 yString 为
? ToString (y )。
7. 让 xSmaller 为 ! IsLessThan (xString ,
yString , true ).
8. 如果 xSmaller 是 true ,返回
-1 𝔽 。
9. 让 ySmaller 为 ! IsLessThan (yString ,
xString , true ).
10. 如果 ySmaller 是 true ,返回
1 𝔽 。
11. 返回 +0 𝔽 。
23.1.3.31 Array.prototype.splice ( start ,
deleteCount ,
...items )
注 1
此方法删除从 整数索引 start 开始的
deleteCount 个数组元素,并用 items 中的元素替换它们。它返回一个包含被删除元素(如果有的话)的数组。
此方法在调用时执行以下步骤:
1. 让 O 为 ? ToObject (this 值)。
2. 让 len 为 ? LengthOfArrayLike (O ).
3. 让 relativeStart 为 ? ToIntegerOrInfinity (start ).
4. 如果 relativeStart = -∞,让 actualStart
为
0。
5. 否则如果 relativeStart < 0,让
actualStart 为 max (len +
relativeStart , 0)。
6. 否则,让 actualStart 为 min (relativeStart ,
len )。
7. 让 itemCount 为 items 中的元素数量。
8. 如果 start 不存在,则
a. 让 actualDeleteCount 为 0。
9. 否则如果 deleteCount 不存在,则
a. 让 actualDeleteCount 为 len -
actualStart 。
10. 否则,
a. 让 dc 为 ? ToIntegerOrInfinity (deleteCount ).
b. 让 actualDeleteCount 为 clamping
dc 在 0 和 len - actualStart 之间的结果。
11. 如果 len + itemCount -
actualDeleteCount > 2** 53 - 1,则抛出
TypeError 异常。
12. 让 A 为 ? ArraySpeciesCreate (O ,
actualDeleteCount ).
13. 让 k 为 0。
14. 重复,直到 k <
actualDeleteCount ,
a. 让 from 为 ! ToString (𝔽 (actualStart +
k ))。
b. 如果 ? HasProperty (O , from ) 为
true ,则
i. 让 fromValue 为 ? Get (O , from ).
ii. 执行 ? CreateDataPropertyOrThrow (A ,
! ToString (𝔽 (k )),
fromValue ).
c. 将 k 设置
为 k + 1。
15. 让 k 为 actualStart +
itemCount - 1。
16. 重复,直到 k < actualStart ,
a. 让 from 为 ! ToString (𝔽 (k ))。
b. 如果 ? HasProperty (O , from ) 为
true ,则
i. 让 fromValue 为 ? Get (O , from ).
ii. 执行 ? CreateDataPropertyOrThrow (O ,
! ToString (𝔽 (k )),
fromValue ).
c. 将 k 设置为 k - 1。
17. 如果 actualDeleteCount > 0,
a. 让 m 为 ? Get (O ,
"length" ).
b. 让 newLen 为 ? ToLength (m -
actualDeleteCount + itemCount ).
c. 执行 ? Set (O ,
"length" , newLen , ? ThrowIfNotExtensible (O )).
18. 返回 A 。
19. 如果 itemCount = 0,且 actualDeleteCount >
0,则
a. 让 m 为 ? Get (O ,
"length" ).
b. 让 newLen 为 ? ToLength (m -
actualDeleteCount ).
c. 执行 ? Set (O ,
"length" , newLen , ? ThrowIfNotExtensible (O )).
20. 如果 itemCount > 0,且 actualDeleteCount =
0,则
a. 让 m 为 ? Get (O ,
"length" ).
b. 让 newLen 为 ? ToLength (m +
itemCount ).
c. 执行 ? Set (O ,
"length" , newLen , ? ThrowIfNotExtensible (O )).
21. 如果 itemCount > 0,且 actualDeleteCount
> 0,则
a. 让 m 为 ? Get (O ,
"length" ).
b. 让 newLen 为 ? ToLength (m -
actualDeleteCount + itemCount ).
c. 执行 ? Set (O ,
"length" , newLen , ? ThrowIfNotExtensible (O )).
注 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 规范中定义;不包含 ECMA-402 支持的实现不得将这些参数位置用于其他目的。
调用此方法时执行以下步骤:
1. 让 array 为 ? ToObject (this 值)。
2. 让 len 为 ? LengthOfArrayLike (array ).
3. 让 separator 为适合于 实现定义
的列表分隔符字符串值,该值适用于 宿主环境 的当前区域设置(如 ",
" )。
4. 让 R 为空字符串。
5. 让 k 为 0。
6. 重复执行,直到 k < len ,
a. 如果 k > 0,则
i. 将 R 设置为 字符串连接
的 R 和 separator 。
b. 让 nextElement 为 ? Get (array , ! ToString (𝔽 (k ))).
c. 如果 nextElement 既不是 undefined
也不是 null ,则
i. 让 S 为 ? ToString (? Invoke (nextElement ,
"toLocaleString" )).
ii. 将 R 设置为 字符串连接
的 R 和 S 。
d. 将 k 设置为 k + 1。
7. 返回 R 。
注 2
该方法将数组的元素转换为字符串,使用它们的 toLocaleString
方法,然后将这些字符串连接起来,用 实现定义 的区域设置分隔符字符串分隔。这种方法类似于
toString
,但旨在根据 宿主环境 的当前区域设置,提供一个敏感于区域设置的结果。
注 3
该方法故意是通用的;它不要求其 this 值是数组。因此,它可以被转移到其他类型的对象上使用作为方法。
23.1.3.33 Array.prototype.toReversed ( )
调用此方法时执行以下步骤:
1. 让 O 为 ? ToObject (this 值)。
2. 让 len 为 ? LengthOfArrayLike (O ).
3. 让 A 为 ? ArrayCreate (len ).
4. 让 k 为 0。
5. 重复执行,直到 k < len ,
a. 让 from 为 ! ToString (𝔽 (len - k
- 1))。
b. 让 Pk 为 ! ToString (𝔽 (k ))。
c. 让 fromValue 为 ? Get (O , from )。
d. 执行 ! CreateDataPropertyOrThrow (A ,
Pk , fromValue )。
e. 将 k 设置为 k + 1。
6. 返回 A 。
23.1.3.34 Array.prototype.toSorted ( comparefn )
调用此方法时执行以下步骤:
1. 如果 comparefn 不是 undefined 且
IsCallable (comparefn ) 是
false ,则抛出 TypeError 异常。
2. 让 O 为 ? ToObject (this 值)。
3. 让 len 为 ? LengthOfArrayLike (O ).
4. 让 A 为 ? ArrayCreate (len )。
5. 让 SortCompare 为一个新的 Abstract Closure ,参数为
(x , y ),捕获 comparefn 并在调用时执行以下步骤:
a. 返回 ? CompareArrayElements (x ,
y , comparefn )。
6. 让 sortedList 为 ? SortIndexedProperties (O , len ,
SortCompare , read-through-holes )。
7. 让 j 为 0。
8. 重复执行,直到 j < len ,
a. 执行 ! CreateDataPropertyOrThrow (A ,
! ToString (𝔽 (j )),
sortedList [j ])。
b. 将 j 设置为 j + 1。
9. 返回 A 。
23.1.3.35 Array.prototype.toSpliced ( start ,
skipCount , ...items )
调用此方法时执行以下步骤:
1. 让 O 为 ? ToObject (this 值)。
2. 让 len 为 ? LengthOfArrayLike (O ).
3. 让 relativeStart 为 ? ToIntegerOrInfinity (start ).
4. 如果 relativeStart 为 -∞,则让 actualStart 为 0。
5. 否则如果 relativeStart < 0,则让 actualStart 为
max (len +
relativeStart , 0)。
6. 否则,让 actualStart 为 min (relativeStart ,
len )。
7. 让 insertCount 为 items 中的元素数量。
8. 如果 start 不存在,则
a. 让 actualSkipCount 为 0。
9. 否则如果 skipCount 不存在,则
a. 让 actualSkipCount 为 len -
actualStart 。
10. 否则,
a. 让 sc 为 ? ToIntegerOrInfinity (skipCount )。
b. 让 actualSkipCount 为 clamping
sc 在 0 和 len - actualStart 之间的结果。
11. 让 newLen 为 len + insertCount -
actualSkipCount 。
12. 如果 newLen > 2** 53 - 1,则抛出 TypeError 异常。
13. 让 A 为 ? ArrayCreate (newLen )。
14. 让 i 为 0。
15. 让 r 为 actualStart +
actualSkipCount 。
16. 重复执行,直到 i < actualStart ,
a. 让 Pi 为 ! ToString (𝔽 (i ))。
b. 让 iValue 为 ? Get (O , Pi )。
c. 执行 ! CreateDataPropertyOrThrow (A ,
Pi , iValue )。
d. 将 i 设置为 i + 1。
17. 对于每个 items 的元素 E ,执行
a. 让 Pi 为 ! ToString (𝔽 (i ))。
b. 执行 ! CreateDataPropertyOrThrow (A ,
Pi , E )。
c. 将 i 设置为 i + 1。
18. 重复执行,直到 i < newLen ,
a. 让 Pi 为 ! ToString (𝔽 (i ))。
b. 让 from 为 ! ToString (𝔽 (r ))。
c. 让 fromValue 为 ? Get (O , from )。
d. 执行 ! CreateDataPropertyOrThrow (A ,
Pi , fromValue )。
e. 将 i 设置为 i + 1。
f. 将 r 设置为 r + 1。
19. 返回 A 。
23.1.3.36 Array.prototype.toString ( )
调用此方法时执行以下步骤:
1. 让 array 为 ? ToObject (this 值)。
2. 让 func 为 ? Get (array , "join" )。
3. 如果 IsCallable (func ) 为
false ,则将 func 设置为内置函数 %Object.prototype.toString%。
4. 返回 ? Call (func ,
array )。
注
此方法故意是通用的;它不要求其 this 值是一个 Array。因此,它可以被转移到其他类型的对象上作为方法使用。
23.1.3.37 Array.prototype.unshift ( ...items )
此方法将参数添加到数组的开头,使得它们在数组中的顺序与在参数列表中的顺序相同。
调用此方法时执行以下步骤:
1. 让 O 为 ? ToObject (this 值)。
2. 让 len 为 ? LengthOfArrayLike (O )。
3. 让 argCount 为 items 中元素的数量。
4. 如果 argCount > 0,则
a. 如果 len + argCount > 2** 53 - 1,则抛出一个 TypeError 异常。
b. 让 k 为 len 。
c. 重复,直到 k > 0,
i. 让 from 为 ! ToString (𝔽 (k - 1))。
ii. 让 to 为 ! ToString (𝔽 (k +
argCount - 1))。
iii. 让 fromPresent 为 ? HasProperty (O , from )。
iv. 如果 fromPresent 为 true ,则
1. 让 fromValue 为 ? Get (O , from )。
2. 执行 ? Set (O , to ,
fromValue , true )。
v. 否则,
1. Assert :fromPresent 为
false 。
2. 执行 ? DeletePropertyOrThrow (O , to )。
vi. 将 k 设为 k - 1。
d. 让 j 为 +0 𝔽 。
e. 对于 items 中的每个元素 E ,执行
i. 执行 ? Set (O , ! ToString (j ),
E , true )。
ii. 将 j 设为 j +
1 𝔽 。
5. 执行 ? Set (O , "length" , 𝔽 (len +
argCount ), true )。
6. 返回 𝔽 (len +
argCount )。
此方法的 "length" 属性为 1 𝔽 。
注
此方法故意是通用的;它不要求其 this 值是一个 Array。因此,它可以被转移到其他类型的对象上作为方法使用。
23.1.3.38 Array.prototype.values ( )
调用此方法时执行以下步骤:
1. 让 O 为 ? ToObject (this 值)。
2. 返回 CreateArrayIterator (O ,
value )。
23.1.3.39 Array.prototype.with ( index , value )
调用此方法时执行以下步骤:
1. 让 O 为 ? ToObject (this 值)。
2. 让 len 为 ? LengthOfArrayLike (O )。
3. 让 relativeIndex 为 ? ToIntegerOrInfinity (index )。
4. 如果 relativeIndex ≥ 0,令 actualIndex 为
relativeIndex 。
5. 否则,令 actualIndex 为 len +
relativeIndex 。
6. 如果 actualIndex ≥ len 或
actualIndex
< 0,抛出一个 RangeError 异常。
7. 让 A 为 ? ArrayCreate (len )。
8. 令 k 为 0。
9. 重复,直到 k
< len ,
a. 令 Pk 为 ! ToString (𝔽 (k ))。
b. 如果 k 是 actualIndex ,则令
fromValue 为 value 。
c. 否则,令 fromValue 为 ? Get (O , Pk )。
d. 执行 ! CreateDataPropertyOrThrow (A ,
Pk , fromValue )。
e. 将 k 设置为 k + 1。
10. 返回 A 。
23.1.3.40 Array.prototype [ @@iterator ] ( )
@@iterator 属性的初始值为
%Array.prototype.values%,定义在 23.1.3.38 。
23.1.3.41 Array.prototype [ @@unscopables ]
@@unscopables 数据属性 的初始值是通过以下步骤创建的:
1. 让 unscopableList 为空对象,通过 OrdinaryObjectCreate (null )
创建。
2. 执行 ! CreateDataPropertyOrThrow (unscopableList ,
"at" , true )。
3. 执行 ! CreateDataPropertyOrThrow (unscopableList ,
"copyWithin" , true )。
4. 执行 ! CreateDataPropertyOrThrow (unscopableList ,
"entries" , true )。
5. 执行 ! CreateDataPropertyOrThrow (unscopableList ,
"fill" , true )。
6. 执行 ! CreateDataPropertyOrThrow (unscopableList ,
"find" , true )。
7. 执行 ! CreateDataPropertyOrThrow (unscopableList ,
"findIndex" , true )。
8. 执行 ! CreateDataPropertyOrThrow (unscopableList ,
"findLast" , true )。
9. 执行 ! CreateDataPropertyOrThrow (unscopableList ,
"findLastIndex" , true )。
10. 执行 ! CreateDataPropertyOrThrow (unscopableList ,
"flat" , true )。
11. 执行 ! CreateDataPropertyOrThrow (unscopableList ,
"flatMap" , true )。
12. 执行 ! CreateDataPropertyOrThrow (unscopableList ,
"includes" , true )。
13. 执行 ! CreateDataPropertyOrThrow (unscopableList ,
"keys" , true )。
14. 执行 ! CreateDataPropertyOrThrow (unscopableList ,
"toReversed" , true )。
15. 执行 ! CreateDataPropertyOrThrow (unscopableList ,
"toSorted" , true )。
16. 执行 ! CreateDataPropertyOrThrow (unscopableList ,
"toSpliced" , true )。
17. 执行 ! CreateDataPropertyOrThrow (unscopableList ,
"values" , true )。
18. 返回 unscopableList 。
此属性具有以下特性 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
true }。
注
该对象的自身属性名是那些在 ECMAScript 2015 规范之前未包含在 Array.prototype
的标准属性名。这些属性名在 with
语句绑定时被忽略,以保留可能使用这些名称作为绑定的现有代码的行为,这些绑定在外部作用域中被 with
语句的绑定对象(数组)所遮蔽。
之所以 "with" 不包含在 unscopableList 中,是因为它已经是一个 保留字 。
23.1.4 数组实例的属性
数组实例是 数组特有对象 ,并具有为此类对象指定的内部方法。数组实例继承自
数组原型对象 的属性。
数组实例具有一个 "length" 属性,以及一组具有 数组索引 名称的可枚举属性。
23.1.4.1 length
数组实例的 "length" 属性是一个 数据属性 ,
其值总是大于每个可配置的自有属性名称的数值,而这些属性名称是 数组索引 。
"length" 属性初始具有属性 { [[Writable]] : true ,
[[Enumerable]] : false , [[Configurable]] : false }。
注
减少 "length" 属性的值会有一个副作用,即删除那些 数组索引
在旧长度值和新长度值之间的自有数组元素。然而,不可配置的属性不能被删除。试图将数组的 "length" 属性设置为一个小于或等于现有不可配置的 数组索引 属性的最大数值的值将导致长度被设置为一个大于该不可配置数值自有
属性名称 的数值。参见 10.4.2.1 。
23.1.5 数组迭代器对象
数组迭代器是一个对象,表示对某个特定数组实例对象的特定迭代。数组迭代器对象没有命名的 构造函数 。相反,数组迭代器对象是通过调用数组实例对象的某些方法创建的。
23.1.5.1 CreateArrayIterator ( array , kind )
抽象操作 CreateArrayIterator 接受参数 array (一个对象)和
kind (key+value 、key 或
value ),并返回一个生成器。它用于为返回此类迭代器的数组方法创建迭代器对象。调用时执行以下步骤:
1. 让 closure 成为一个新的 抽象闭包 ,该闭包没有参数,捕获
kind 和 array ,并在调用时执行以下步骤:
a. 让 index 为 0。
b. 重复以下操作:
i. 如果 array 有一个 [[TypedArrayName]] 内部槽,则:
1. 让 taRecord 为 使用缓冲区证人记录创建类型化数组 (array ,
seq-cst )。
2. 如果 类型化数组超出范围 (taRecord )
为 true ,则抛出一个 TypeError 异常。
3. 让 len 为 类型化数组长度 (taRecord )。
ii. 否则:
1. 让 len 为 ? 类似数组的长度 (array )。
iii. 如果 index ≥ len ,则返回
正常完成 (undefined )。
iv. 让 indexNumber 为 𝔽 (index )。
v. 如果 kind 为 key ,则:
1. 让 result 为 indexNumber 。
vi. 否则:
1. 让 elementKey 为 ! 转换为字符串 (indexNumber )。
2. 让 elementValue 为 ? 获取 (array , elementKey )。
3. 如果 kind 为 value ,则:
a. 让 result 为 elementValue 。
4. 否则:
a. 断言 : kind 为
key+value 。
b. 让 result 为 从列表创建数组 («
indexNumber , elementValue »)。
vii. 执行 ? 生成器产出 (创建迭代结果对象 (result ,
false ))。
viii. 将 index 设置为 index + 1。
2. 返回 从闭包创建迭代器 (closure ,
"%ArrayIteratorPrototype%" , %ArrayIteratorPrototype% )。
23.1.5.2 %ArrayIteratorPrototype% 对象
%ArrayIteratorPrototype% 对象:
23.1.5.2.1 %ArrayIteratorPrototype%.next ( )
1. 返回 ? GeneratorResume (this 值,
empty , "%ArrayIteratorPrototype%" ).
23.1.5.2.2 %ArrayIteratorPrototype% [ @@toStringTag ]
@@toStringTag 属性的初始值是字符串值
"Array Iterator" 。
此属性具有 { [[Writable]] : false ,
[[Enumerable]] : false , [[Configurable]] : true } 的属性。
23.2 TypedArray 对象
一个 TypedArray 表示底层二进制数据缓冲区的类似数组的视图 (25.1 )。 TypedArray 元素类型 是所有 TypedArray
实例元素的底层二进制标量数据类型。每种支持的元素类型都有一个独特的 TypedArray 构造函数 ,在 Table 71 中列出。每个在
Table 71 中的 构造函数
都有一个对应的独特原型对象。
表格 71:TypedArray 构造函数
构造函数 名称和内部对象
元素类型
元素大小
转换操作
描述
Int8Array
%Int8Array%
int8
1
ToInt8
8 位二进制补码有符号 整数
Uint8Array
%Uint8Array%
uint8
1
ToUint8
8 位无符号 整数
Uint8ClampedArray
%Uint8ClampedArray%
uint8clamped
1
ToUint8Clamp
8 位无符号 整数 (夹紧转换)
Int16Array
%Int16Array%
int16
2
ToInt16
16 位二进制补码有符号 整数
Uint16Array
%Uint16Array%
uint16
2
ToUint16
16 位无符号 整数
Int32Array
%Int32Array%
int32
4
ToInt32
32 位二进制补码有符号 整数
Uint32Array
%Uint32Array%
uint32
4
ToUint32
32 位无符号 整数
BigInt64Array
%BigInt64Array%
bigint64
8
ToBigInt64
64 位二进制补码有符号 整数
BigUint64Array
%BigUint64Array%
biguint64
8
ToBigUint64
64 位无符号 整数
Float32Array
%Float32Array%
float32
4
32 位 IEEE 浮点数
Float64Array
%Float64Array%
float64
8
64 位 IEEE 浮点数
在下面的定义中,对 TypedArray 的引用应替换为上述表格中相应的 构造函数 名称。
23.2.1 %TypedArray% 内在对象
%TypedArray% 内在对象:
是一个构造函数 的函数对象 ,所有的TypedArray
构造函数 对象都继承自它。
连同其对应的原型对象,提供了所有TypedArray 构造函数 及其实例继承的通用属性。
没有全局名称,也不会作为全局对象 的属性出现。
充当各种TypedArray 构造函数 的抽象超类。
在被调用时会抛出错误,因为它是一个抽象类构造函数 。TypedArray 构造函数 不会向它执行super
调用。
23.2.1.1 %TypedArray% ( )
调用此函数时执行以下步骤:
1. 抛出一个TypeError 异常。
此函数的"length" 属性为+0 𝔽 。
23.2.2 %TypedArray% 内在对象的属性
%TypedArray% 内在对象:%TypedArray%
内在对象:
23.2.2.1 %TypedArray%.from ( source [ , mapfn [ ,
thisArg ] ] )
调用此方法时执行以下步骤:
1. 令C 为this 的值。
2. 如果IsConstructor (C )
的结果为false ,则抛出TypeError 异常。
3. 如果mapfn 为undefined ,则
a. 令mapping 为false 。
4. 否则,
a. 如果IsCallable (mapfn )
的结果为false ,则抛出TypeError 异常。
b. 令mapping 为true 。
5. 令usingIterator 为? GetMethod (source , @@iterator )。
6. 如果usingIterator 不是undefined ,
则
a. 令values 为? IteratorToList (?GetIteratorFromMethod (source ,
usingIterator ))。
b. 令len 为values 的元素数量。
c. 令targetObj 为? TypedArrayCreateFromConstructor (C ,«
𝔽 (len ) »)。
d. 令k 为0。
e. 重复,当k < len 时,
i. 令Pk 为! ToString (𝔽 (k ))。
ii. 令kValue 为values 的第一个元素。
iii. 从values 中移除第一个元素。
iv. 如果mapping 为true ,
则
1. 令mappedValue 为? Call (mapfn ,thisArg ,«
kValue ,𝔽 (k ) »)。
v. 否则,
1. 令mappedValue 为kValue 。
vi. 执行? Set (targetObj ,Pk ,
mappedValue ,true )。
vii. 将k 设置为k + 1。
f. Assert :现在values 是一个空的List 。
g. 返回targetObj 。
7. 注意:source 不是可迭代的,因此假设它已经是类数组对象 。
8. 令arrayLike 为! ToObject (source )。
9. 令len 为? LengthOfArrayLike (arrayLike )。
10. 令targetObj 为? TypedArrayCreateFromConstructor (C ,« 𝔽 (len ) »)。
11. 令k 为0。
12. 重复,当k < len 时,
a. 令Pk 为! ToString (𝔽 (k ))。
b. 令kValue 为? Get (arrayLike ,Pk )。
c. 如果mapping 为true ,则
i. 令mappedValue 为? Call (mapfn ,thisArg ,«
kValue ,𝔽 (k ) »)。
d. 否则,
i. 令mappedValue 为kValue 。
e. 执行? Set (targetObj ,Pk ,
mappedValue ,true )。
f. 将k 设置为k + 1。
13. 返回targetObj 。
23.2.2.2 %TypedArray%.of ( ...items )
调用此方法时执行以下步骤:
1. 令len 为items 中的元素数量。
2. 令C 为this 的值。
3. 如果IsConstructor (C )的结果为false ,则抛出TypeError 异常。
4. 令newObj 为? TypedArrayCreateFromConstructor (C ,« 𝔽 (len ) »)。
5. 令k 为0。
6. 重复,当k < len 时,
a. 令kValue 为items [k ]。
b. 令Pk 为! ToString (𝔽 (k ))。
c. 执行? Set (newObj ,Pk ,kValue ,true )。
d. 将k 设置为k + 1。
7. 返回newObj 。
23.2.2.3 %TypedArray%.prototype
%TypedArray% .prototype
的初始值是 %TypedArray%
prototype object 。
该属性具有以下属性:{ [[Writable]] : false ,
[[Enumerable]] : false , [[Configurable]] :
false }。
23.2.2.4 get %TypedArray% [ @@species ]
%TypedArray% [@@species]
是一个访问器属性 ,其设置访问器函数为undefined 。其获取访问器函数在调用时执行以下步骤:
1. 返回this 值。
该函数的"name" 属性的值为"get [Symbol.species]" 。
注
23.2.3 %TypedArray% 原型对象的属性
%TypedArray% 原型对象 :
具有一个[[Prototype]] 内部插槽,其值为%Object.prototype% 。
是%TypedArray.prototype% 。
是一个普通对象 。
没有[[ViewedArrayBuffer]] 或者任何特定于TypedArray 实例对象的其他内部插槽。
23.2.3.1 %TypedArray%.prototype.at ( index )
1. 将 O 设为 this 的值。
2. 将 taRecord 设为 ? ValidateTypedArray (O ,
seq-cst ).
3. 将 len 设为 TypedArrayLength (taRecord ).
4. 将 relativeIndex 设为 ? ToIntegerOrInfinity (index ).
5. 如果 relativeIndex ≥ 0,则
a. 将 k 设为 relativeIndex 。
6. 否则,
a. 将 k 设为 len +
relativeIndex 。
7. 如果 k < 0 或 k ≥ len ,
返回
undefined 。
8. 返回 ! Get (O , ! ToString (𝔽 (k ))).
23.2.3.2 获取 %TypedArray%.prototype.buffer
%TypedArray% .prototype.buffer
是一个 访问器属性 ,其设置
访问器函数是 undefined 。其获取
访问器函数在调用时执行以下步骤:
1. 将 O 设为 this 的值。
2. 执行 ? RequireInternalSlot (O ,
[[TypedArrayName]] ).
3. Assert : O 具有一个 [[ViewedArrayBuffer]] 内部槽。
4. 将 buffer 设为 O .[[ViewedArrayBuffer]] 。
5. 返回 buffer 。
23.2.3.3 获取 %TypedArray%.prototype.byteLength
%TypedArray% .prototype.byteLength
是一个 访问器属性 ,其设置
访问器函数是 undefined 。其获取
访问器函数在调用时执行以下步骤:
1. 将 O 设为 this 的值。
2. 执行 ? RequireInternalSlot (O ,
[[TypedArrayName]] ).
3. Assert : O 具有一个 [[ViewedArrayBuffer]] 内部槽。
4. 将 taRecord 设为 MakeTypedArrayWithBufferWitnessRecord (O ,
seq-cst ).
5. 将 size 设为 TypedArrayByteLength (taRecord ).
6. 返回 𝔽 (size ).
23.2.3.4 获取 %TypedArray%.prototype.byteOffset
%TypedArray% .prototype.byteOffset
是一个 访问器属性 ,其设置
访问器函数是 undefined 。其获取
访问器函数在调用时执行以下步骤:
1. 将 O 设为 this 的值。
2. 执行 ? RequireInternalSlot (O ,
[[TypedArrayName]] ).
3. Assert : O 具有一个 [[ViewedArrayBuffer]] 内部槽。
4. 将 taRecord 设为 MakeTypedArrayWithBufferWitnessRecord (O ,
seq-cst ).
5. 如果 IsTypedArrayOutOfBounds (taRecord )
为 true ,返回 +0 𝔽 。
6. 将 offset 设为 O .[[ByteOffset]] 。
7. 返回 𝔽 (offset ).
23.2.3.5 %TypedArray%.prototype.constructor
%TypedArray% .prototype.constructor
的初始值是 %TypedArray% 。
23.2.3.6 %TypedArray%.prototype.copyWithin ( target ,
start [ , end ] )
该方法的参数解释和使用与 Array.prototype.copyWithin
相同,如在 23.1.3.4 中定义。
该方法在调用时执行以下步骤:
1. 将 O 设为 this 值。
2. 将 taRecord 设为 ? ValidateTypedArray (O ,
seq-cst ).
3. 将 len 设为 TypedArrayLength (taRecord ).
4. 将 relativeTarget 设为 ? ToIntegerOrInfinity (target ).
5. 如果 relativeTarget = -∞,则将 targetIndex
设为 0。
6. 否则,如果 relativeTarget < 0,则将
targetIndex 设为 max (len +
relativeTarget , 0).
7. 否则,将 targetIndex 设为 min (relativeTarget ,
len ).
8. 将 relativeStart 设为 ? ToIntegerOrInfinity (start ).
9. 如果 relativeStart = -∞,则将 startIndex
设为 0。
10. 否则,如果 relativeStart < 0,则将
startIndex 设为 max (len +
relativeStart , 0).
11. 否则,将 startIndex 设为 min (relativeStart ,
len ).
12. 如果 end 为 undefined ,则将
relativeEnd 设为 len ;否则将 relativeEnd 设为 ? ToIntegerOrInfinity (end ).
13. 如果 relativeEnd = -∞,则将 endIndex
设为 0。
14. 否则,如果 relativeEnd < 0,则将
endIndex
设为 max (len +
relativeEnd , 0).
15. 否则,将 endIndex 设为 min (relativeEnd ,
len ).
16. 将 count 设为 min (endIndex
-
startIndex , len - targetIndex ).
17. 如果 count > 0,则
a. 注意:复制必须以保持源数据的位级编码的方式执行。
b. 将 buffer 设为 O .[[ViewedArrayBuffer]] 。
c. 将 taRecord 设为 MakeTypedArrayWithBufferWitnessRecord (O ,
seq-cst ).
d. 如果 IsTypedArrayOutOfBounds (taRecord )
为 true ,则抛出 TypeError 异常。
e. 将 len 设为 TypedArrayLength (taRecord ).
f. 将 elementSize 设为 TypedArrayElementSize (O ).
g. 将 byteOffset 设为 O .[[ByteOffset]] .
h. 将 bufferByteLimit 设为 (len ×
elementSize ) + byteOffset .
i. 将 toByteIndex 设为 (targetIndex ×
elementSize ) + byteOffset .
j. 将 fromByteIndex 设为 (startIndex ×
elementSize ) + byteOffset .
k. 将 countBytes 设为 count ×
elementSize .
l. 如果 fromByteIndex < toByteIndex
且
toByteIndex < fromByteIndex + countBytes ,则
i. 将 direction 设为 -1。
ii. 将 fromByteIndex 设为
fromByteIndex
+ countBytes - 1。
iii. 将 toByteIndex 设为
toByteIndex
+
countBytes - 1。
m. 否则,
i. 将 direction 设为 1。
n. 重复,直到 countBytes > 0,
i. 如果 fromByteIndex <
bufferByteLimit 且 toByteIndex < bufferByteLimit ,
则
1. 将 value 设为 GetValueFromBuffer (buffer ,
fromByteIndex , uint8 , true ,
unordered ).
2. 执行 SetValueInBuffer (buffer ,
toByteIndex , uint8 , value ,
true , unordered ).
3. 将 fromByteIndex 设为
fromByteIndex + direction .
4. 将 toByteIndex 设为
toByteIndex
+ direction .
5. 将 countBytes 设为
countBytes
-
1.
ii. 否则,
1. 将 countBytes 设为 0。
18. 返回 O 。
23.2.3.7 %TypedArray%.prototype.entries ( )
该方法在调用时执行以下步骤:
1. 将 O 设为 this 值。
2. 执行 ? ValidateTypedArray (O ,
seq-cst ).
3. 返回 CreateArrayIterator (O ,
key+value ).
23.2.3.8 %TypedArray%.prototype.every ( callbackfn [ ,
thisArg ] )
该方法的参数解释和使用方式与 Array.prototype.every
在 23.1.3.6
中定义的一致。
该方法在调用时执行以下步骤:
1. 将 O 设为 this 值。
2. 将 taRecord 设为 ? ValidateTypedArray (O ,
seq-cst ).
3. 将 len 设为 TypedArrayLength (taRecord ).
4. 如果 IsCallable (callbackfn )
为 false ,则抛出 TypeError 异常。
5. 将 k 设为 0。
6. 重复执行,直到 k < len ,
a. 将 Pk 设为 ! ToString (𝔽 (k )).
b. 将 kValue 设为 ! Get (O ,
Pk ).
c. 将 testResult 设为 ToBoolean (?
Call (callbackfn , thisArg , «
kValue , 𝔽 (k ),
O »)).
d. 如果 testResult 为 false ,则返回
false 。
e. 将 k 设为 k + 1。
7. 返回 true 。
该方法不是通用的。this 值必须是一个具有 [[TypedArrayName]] 内部插槽的对象。
23.2.3.9 %TypedArray%.prototype.fill ( value [ ,
start
[ , end ] ] )
该方法的参数解释和使用方式与 Array.prototype.fill
在 23.1.3.7
中定义的一致。
该方法在调用时执行以下步骤:
1. 将 O 设为 this 值。
2. 将 taRecord 设为 ? ValidateTypedArray (O ,
seq-cst ).
3. 将 len 设为 TypedArrayLength (taRecord ).
4. 如果 O .[[ContentType]] 是
bigint ,将 value 设为 ? ToBigInt (value ).
5. 否则,将 value 设为 ? ToNumber (value ).
6. 将 relativeStart 设为 ? ToIntegerOrInfinity (start ).
7. 如果 relativeStart = -∞,将 startIndex
设为 0。
8. 否则如果 relativeStart < 0,将
startIndex 设为 max (len +
relativeStart , 0).
9. 否则,将 startIndex 设为 min (relativeStart ,
len ).
10. 如果 end 为 undefined ,将
relativeEnd 设为 len ;否则将 relativeEnd 设为 ? ToIntegerOrInfinity (end ).
11. 如果 relativeEnd = -∞,将 endIndex 设为
0。
12. 否则如果 relativeEnd < 0,将
endIndex
设为 max (len +
relativeEnd , 0).
13. 否则,将 endIndex 设为 min (relativeEnd ,
len ).
14. 将 taRecord 设为 MakeTypedArrayWithBufferWitnessRecord (O ,
seq-cst ).
15. 如果 IsTypedArrayOutOfBounds (taRecord )
为 true ,则抛出 TypeError 异常。
16. 将 len 设为 TypedArrayLength (taRecord ).
17. 将 endIndex 设为 min (endIndex ,
len ).
18. 将 k 设为 startIndex 。
19. 重复执行,直到 k < endIndex ,
a. 将 Pk 设为 ! ToString (𝔽 (k )).
b. 执行 ! Set (O ,
Pk , value , true ).
c. 将 k 设为 k + 1。
20. 返回 O 。
23.2.3.10 %TypedArray%.prototype.filter ( callbackfn [ ,
thisArg ] )
该方法的参数解释和使用方式与 Array.prototype.filter
在 23.1.3.8
中定义的一致。
该方法在调用时执行以下步骤:
1. 将 O 设为 this 值。
2. 将 taRecord 设为 ? ValidateTypedArray (O ,
seq-cst ).
3. 将 len 设为 TypedArrayLength (taRecord ).
4. 如果 IsCallable (callbackfn )
为 false ,则抛出 TypeError 异常。
5. 将 kept 设为一个新的空 List 。
6. 将 captured 设为 0。
7. 将 k 设为 0。
8. 重复执行,直到 k < len ,
a. 将 Pk 设为 ! ToString (𝔽 (k )).
b. 将 kValue 设为 ! Get (O ,
Pk ).
c. 将 selected 设为 ToBoolean (?
Call (callbackfn , thisArg , «
kValue , 𝔽 (k ),
O »)).
d. 如果 selected 为 true ,则
i. 将 kValue 添加到 kept 。
ii. 将 captured 设为 captured + 1。
e. 将 k 设为 k + 1。
9. 将 A 设为 ? TypedArraySpeciesCreate (O , « 𝔽 (captured ) »).
10. 将 n 设为 0。
11. 对 kept 的每个元素 e 执行
a. 执行 ! Set (A ,
! ToString (𝔽 (n )),
e , true ).
b. 将 n 设为 n + 1。
12. 返回 A 。
该方法不是通用的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。
23.2.3.11 %TypedArray%.prototype.find ( predicate [ ,
thisArg ] )
该方法的参数解释和使用方式与 Array.prototype.find
在 23.1.3.9
中定义的一致。
该方法在调用时执行以下步骤:
1. 将 O 设为 this 值。
2. 将 taRecord 设为 ? ValidateTypedArray (O ,
seq-cst ).
3. 将 len 设为 TypedArrayLength (taRecord ).
4. 将 findRec 设为 ? FindViaPredicate (O , len ,
ascending , predicate , thisArg ).
5. 返回 findRec .[[Value]] 。
该方法不是通用的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。
23.2.3.12 %TypedArray%.prototype.findIndex ( predicate [ ,
thisArg ] )
该方法的参数解释和使用方式与 Array.prototype.findIndex
在 23.1.3.10
中定义的一致。
该方法在调用时执行以下步骤:
1. 将 O 设为 this 值。
2. 将 taRecord 设为 ? ValidateTypedArray (O ,
seq-cst ).
3. 将 len 设为 TypedArrayLength (taRecord ).
4. 将 findRec 设为 ? FindViaPredicate (O , len ,
ascending , predicate , thisArg ).
5. 返回 findRec .[[Index]] 。
该方法不是通用的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。
23.2.3.13 %TypedArray%.prototype.findLast ( predicate [ ,
thisArg ] )
该方法的参数解释和使用方式与 Array.prototype.findLast
在 23.1.3.11
中定义的一致。
该方法在调用时执行以下步骤:
1. 将 O 设为 this 值。
2. 将 taRecord 设为 ? ValidateTypedArray (O ,
seq-cst ).
3. 将 len 设为 TypedArrayLength (taRecord ).
4. 将 findRec 设为 ? FindViaPredicate (O , len ,
descending , predicate , thisArg ).
5. 返回 findRec .[[Value]] 。
该方法不是通用的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。
23.2.3.14 %TypedArray%.prototype.findLastIndex ( predicate [
,
thisArg ] )
该方法的参数解释和使用方式与 Array.prototype.findLastIndex
在 23.1.3.12
中定义的一致。
该方法在调用时执行以下步骤:
1. 将 O 设为 this 值。
2. 将 taRecord 设为 ? ValidateTypedArray (O ,
seq-cst ).
3. 将 len 设为 TypedArrayLength (taRecord ).
4. 将 findRec 设为 ? FindViaPredicate (O , len ,
descending , predicate , thisArg ).
5. 返回 findRec .[[Index]] 。
该方法不是通用的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。
23.2.3.15 %TypedArray%.prototype.forEach ( callbackfn [ ,
thisArg ] )
该方法的参数解释和使用方式与 Array.prototype.forEach
在 23.1.3.15
中定义的一致。
该方法在调用时执行以下步骤:
1. 将 O 设为 this 值。
2. 将 taRecord 设为 ? ValidateTypedArray (O ,
seq-cst ).
3. 将 len 设为 TypedArrayLength (taRecord ).
4. 如果 IsCallable (callbackfn )
为 false ,则抛出 TypeError 异常。
5. 将 k 设为 0。
6. 重复以下步骤,直到 k < len :
a. 将 Pk 设为 ! ToString (𝔽 (k )).
b. 将 kValue 设为 ! Get (O ,
Pk ).
c. 执行 ? Call (callbackfn , thisArg , «
kValue , 𝔽 (k ),
O »).
d. 将 k 设为 k + 1。
7. 返回 undefined 。
该方法不是通用的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。
23.2.3.16 %TypedArray%.prototype.includes ( searchElement [ ,
fromIndex ] )
该方法的参数解释和使用方式与 Array.prototype.includes
在 23.1.3.16
中定义的一致。
该方法在调用时执行以下步骤:
1. 将 O 设为 this 值。
2. 将 taRecord 设为 ? ValidateTypedArray (O ,
seq-cst ).
3. 将 len 设为 TypedArrayLength (taRecord ).
4. 如果 len 等于 0,则返回 false 。
5. 将 n 设为 ? ToIntegerOrInfinity (fromIndex ).
6. Assert : 如果 fromIndex 为
undefined ,则 n 为 0。
7. 如果 n 等于 +∞,则返回 false 。
8. 否则如果 n 等于 -∞,将 n 设为 0。
9. 如果 n ≥ 0,则
a. 将 k 设为 n 。
10. 否则,
a. 将 k 设为 len + n 。
b. 如果 k
< 0,将 k 设为 0。
11. 重复以下步骤,直到 k
< len :
a. 将 elementK 设为 ! Get (O ,
! ToString (𝔽 (k ))).
b. 如果 SameValueZero (searchElement ,
elementK ) 为 true ,则返回 true 。
c. 将 k 设为 k + 1。
12. 返回 false 。
该方法不是通用的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。
23.2.3.17 %TypedArray%.prototype.indexOf ( searchElement [ ,
fromIndex ] )
该方法的参数解释和使用方式与 Array.prototype.indexOf
在 23.1.3.17
中定义的一致。
该方法在调用时执行以下步骤:
1. 将 O 设为 this 值。
2. 将 taRecord 设为 ? ValidateTypedArray (O ,
seq-cst ).
3. 将 len 设为 TypedArrayLength (taRecord ).
4. 如果 len 等于 0,则返回
-1 𝔽 。
5. 将 n 设为 ? ToIntegerOrInfinity (fromIndex ).
6. Assert : 如果 fromIndex 为
undefined ,则 n 为 0。
7. 如果 n 等于 +∞,则返回
-1 𝔽 。
8. 否则如果 n 等于 -∞,将 n 设为 0。
9. 如果 n ≥ 0,则
a. 将 k 设为 n 。
10. 否则,
a. 将 k 设为 len + n 。
b. 如果 k
< 0,将 k 设为 0。
11. 重复以下步骤,直到 k
< len :
a. 将 kPresent 设为 ! HasProperty (O ,
! ToString (𝔽 (k ))).
b. 如果 kPresent 为 true ,则
i. 将 elementK 设为 ! Get (O ,
! ToString (𝔽 (k ))).
ii. 如果 IsStrictlyEqual (searchElement ,
elementK ) 为 true ,则返回 𝔽 (k ).
c. 将 k 设为 k + 1。
12. 返回 -1 𝔽 。
该方法不是通用的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。
23.2.3.18 %TypedArray%.prototype.join ( separator )
该方法的参数解释和使用方式与 Array.prototype.join
在 23.1.3.18
中定义的一致。
该方法在调用时执行以下步骤:
1. 将 O 设为 this 值。
2. 将 taRecord 设为 ? ValidateTypedArray (O ,
seq-cst ).
3. 将 len 设为 TypedArrayLength (taRecord ).
4. 如果 separator 为 undefined ,则将
sep 设为 "," 。
5. 否则,将 sep 设为 ? ToString (separator ).
6. 将 R 设为空字符串。
7. 将 k 设为 0。
8. 重复以下步骤,直到 k
< len :
a. 如果 k > 0,则将 R 设为 string-concatenation
的 R 和 sep 。
b. 将 element 设为 ! Get (O ,
! ToString (𝔽 (k ))).
c. 如果 element 为 undefined ,则将
next 设为空字符串;否则,将 next 设为 ! ToString (element )。
d. 将 R 设为 string-concatenation
的 R 和 next 。
e. 将 k 设为 k + 1。
9. 返回 R 。
该方法不是通用的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。
23.2.3.19 %TypedArray%.prototype.keys ( )
该方法在调用时执行以下步骤:
1. 将 O 设为 this 值。
2. 执行 ? ValidateTypedArray (O ,
seq-cst ).
3. 返回 CreateArrayIterator (O ,
key ).
23.2.3.20 %TypedArray%.prototype.lastIndexOf ( searchElement
[
,
fromIndex ] )
该方法的参数解释和使用方式与 Array.prototype.lastIndexOf
相同,如 23.1.3.20 中定义。
该方法在调用时执行以下步骤:
1. 将 O 设为 this 值。
2. 将 taRecord 设为 ? ValidateTypedArray (O ,
seq-cst ).
3. 将 len 设为 TypedArrayLength (taRecord ).
4. 如果 len = 0,则返回
-1 𝔽 .
5. 如果 fromIndex 存在,则将 n 设为
? ToIntegerOrInfinity (fromIndex ); 否则将 n 设为
len - 1.
6. 如果 n = -∞,则返回
-1 𝔽 .
7. 如果 n ≥ 0,则
a. 将 k 设为 min (n ,
len - 1).
8. 否则,
a. 将 k 设为 len + n .
9. 重复,直到 k ≥ 0,
a. 将 kPresent 设为 ! HasProperty (O ,
! ToString (𝔽 (k ))).
b. 如果 kPresent 为 true ,则
i. 将 elementK 设为 ! Get (O ,
! ToString (𝔽 (k ))).
ii. 如果 IsStrictlyEqual (searchElement ,
elementK ) 为 true ,返回 𝔽 (k ).
c. 将 k 设为 k - 1.
10. 返回 -1 𝔽 .
该方法不是通用的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。
23.2.3.21 get %TypedArray%.prototype.length
%TypedArray% .prototype.length
是一个 访问器属性 ,其设置访问器函数为
undefined 。其获取访问器函数在调用时执行以下步骤:
1. 将 O 设为 this 值。
2. 执行 ? RequireInternalSlot (O ,
[[TypedArrayName]] ).
3. Assert : O 具有 [[ViewedArrayBuffer]] 和 [[ArrayLength]] 内部槽。
4. 将 taRecord 设为 MakeTypedArrayWithBufferWitnessRecord (O ,
seq-cst ).
5. 如果 IsTypedArrayOutOfBounds (taRecord )
为 true ,返回 +0 𝔽 .
6. 将 length 设为 TypedArrayLength (taRecord ).
7. 返回 𝔽 (length ).
此函数不是通用的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。
23.2.3.22 %TypedArray%.prototype.map ( callbackfn [ ,
thisArg ] )
此方法的参数解释和使用与 Array.prototype.map
相同,如 23.1.3.21 所定义。
此方法在调用时执行以下步骤:
1. 将 O 设为 this 值。
2. 将 taRecord 设为 ? ValidateTypedArray (O ,
seq-cst ).
3. 将 len 设为 TypedArrayLength (taRecord ).
4. 如果 IsCallable (callbackfn )
为 false ,则抛出 TypeError 异常。
5. 将 A 设为 ? TypedArraySpeciesCreate (O , « 𝔽 (len ) »).
6. 将 k 设为 0。
7. 重复,直到 k < len ,
a. 将 Pk 设为 ! ToString (𝔽 (k )).
b. 将 kValue 设为 ! Get (O ,
Pk ).
c. 将 mappedValue 设为 ? Call (callbackfn , thisArg , «
kValue , 𝔽 (k ),
O »).
d. 执行 ? Set (A , Pk ,
mappedValue ,
true ).
e. 将 k 设为 k + 1。
8. 返回 A 。
此方法不是通用的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。
23.2.3.23 %TypedArray%.prototype.reduce ( callbackfn [ ,
initialValue ] )
此方法的参数解释和使用与 Array.prototype.reduce
相同,如 23.1.3.24
所定义。
此方法在调用时执行以下步骤:
1. 将 O 设为 this 值。
2. 将 taRecord 设为 ? ValidateTypedArray (O ,
seq-cst ).
3. 将 len 设为 TypedArrayLength (taRecord ).
4. 如果 IsCallable (callbackfn )
为 false ,则抛出 TypeError 异常。
5. 如果 len 为 0 并且 initialValue 不存在,
则抛出 TypeError 异常。
6. 将 k 设为 0。
7. 将 accumulator 设为 undefined 。
8. 如果存在 initialValue ,则
a. 将 accumulator 设为 initialValue 。
9. 否则,
a. 将 Pk 设为 ! ToString (𝔽 (k )).
b. 将 accumulator 设为 ! Get (O ,
Pk ).
c. 将 k 设为 k + 1。
10. 重复,直到 k < len ,
a. 将 Pk 设为 ! ToString (𝔽 (k )).
b. 将 kValue 设为 ! Get (O ,
Pk ).
c. 将 accumulator 设为 ? Call (callbackfn ,
undefined ,
«
accumulator , kValue , 𝔽 (k ),
O »).
d. 将 k 设为 k + 1。
11. 返回 accumulator 。
此方法不是通用的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。
23.2.3.24 %TypedArray%.prototype.reduceRight ( callbackfn [ ,
initialValue ] )
此方法的参数解释和使用与 Array.prototype.reduceRight
相同,如 23.1.3.25 所定义。
此方法在调用时执行以下步骤:
1. 将 O 设为 this 值。
2. 将 taRecord 设为 ? ValidateTypedArray (O ,
seq-cst ).
3. 将 len 设为 TypedArrayLength (taRecord ).
4. 如果 IsCallable (callbackfn )
为 false ,则抛出 TypeError 异常。
5. 如果 len 为 0 并且 initialValue 不存在,
则抛出 TypeError 异常。
6. 将 k 设为 len - 1。
7. 将 accumulator 设为 undefined 。
8. 如果存在 initialValue ,则
a. 将 accumulator 设为 initialValue 。
9. 否则,
a. 将 Pk 设为 ! ToString (𝔽 (k )).
b. 将 accumulator 设为 ! Get (O ,
Pk ).
c. 将 k 设为 k - 1。
10. 重复,直到 k ≥ 0,
a. 将 Pk 设为 ! ToString (𝔽 (k )).
b. 将 kValue 设为 ! Get (O ,
Pk ).
c. 将 accumulator 设为 ? Call (callbackfn ,
undefined ,
«
accumulator , kValue , 𝔽 (k ),
O »).
d. 将 k 设为 k - 1。
11. 返回 accumulator 。
此方法不是通用的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。
23.2.3.25 %TypedArray%.prototype.reverse ( )
此方法的参数解释和使用与 Array.prototype.reverse
相同,如 23.1.3.26
所定义。
此方法在调用时执行以下步骤:
1. 将 O 设为 this 值。
2. 将 taRecord 设为 ? ValidateTypedArray (O ,
seq-cst ).
3. 将 len 设为 TypedArrayLength (taRecord ).
4. 将 middle 设为 floor (len
/
2).
5. 将 lower 设为 0。
6. 重复,直到 lower ≠ middle ,
a. 将 upper 设为 len - lower
-
1。
b. 将 upperP 设为 ! ToString (𝔽 (upper )).
c. 将 lowerP 设为 ! ToString (𝔽 (lower )).
d. 将 lowerValue 设为 ! Get (O ,
lowerP ).
e. 将 upperValue 设为 ! Get (O ,
upperP ).
f. 执行 ! Set (O ,
lowerP , upperValue , true ).
g. 执行 ! Set (O ,
upperP , lowerValue , true ).
h. 将 lower 设为 lower + 1。
7. 返回 O 。
此方法不是通用的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。
23.2.3.26 %TypedArray%.prototype.set ( source [ ,
offset ] )
此方法在 TypedArray 中设置多个值,从 source 读取值。根据 source 的类型,细节有所不同。可选的
offset 值表示在此 TypedArray 中开始写入值的第一个元素索引。如果省略,则默认为 0。
调用时执行以下步骤:
1. 将 target 设为 this 值。
2. 执行 ? RequireInternalSlot (target ,
[[TypedArrayName]] ).
3. Assert : target 具有 [[ViewedArrayBuffer]] 内部槽。
4. 将 targetOffset 设为 ? ToIntegerOrInfinity (offset ).
5. 如果 targetOffset < 0,则抛出
RangeError 异常。
6. 如果 source 是一个对象
且具有 [[TypedArrayName]] 内部槽,则
a. 执行 ? SetTypedArrayFromTypedArray (target ,
targetOffset , source ).
7. 否则,
a. 执行 ? SetTypedArrayFromArrayLike (target ,
targetOffset , source ).
8. 返回 undefined 。
此方法不是通用的。this 值必须是一个具有 [[TypedArrayName]] 内部槽的对象。
23.2.3.26.1 SetTypedArrayFromTypedArray ( target ,
targetOffset , source )
抽象操作 SetTypedArrayFromTypedArray 接受以下参数:target (一个 TypedArray )、targetOffset (一个非负的
整数
或 +∞)以及 source (一个 TypedArray ),并返回一个 正常完成记录 (包含
unused )或一个 抛出完成记录 。它在
target 中设置多个值,从 targetOffset 开始,值从 source 中读取。调用时执行以下步骤:
1. 设定 targetBuffer 为 target .[[ViewedArrayBuffer]] 。
2. 设定 targetRecord 为 MakeTypedArrayWithBufferWitnessRecord (target ,
seq-cst )。
3. 如果 IsTypedArrayOutOfBounds (targetRecord )
为 true ,则抛出 TypeError 异常。
4. 设定 targetLength 为 TypedArrayLength (targetRecord )。
5. 设定 srcBuffer 为 source .[[ViewedArrayBuffer]] 。
6. 设定 srcRecord 为 MakeTypedArrayWithBufferWitnessRecord (source ,
seq-cst )。
7. 如果 IsTypedArrayOutOfBounds (srcRecord )
为 true ,则抛出 TypeError 异常。
8. 设定 srcLength 为 TypedArrayLength (srcRecord )。
9. 设定 targetType 为 TypedArrayElementType (target )。
10. 设定 targetElementSize 为 TypedArrayElementSize (target )。
11. 设定 targetByteOffset 为 target .[[ByteOffset]] 。
12. 设定 srcType 为 TypedArrayElementType (source )。
13. 设定 srcElementSize 为 TypedArrayElementSize (source )。
14. 设定 srcByteOffset 为 source .[[ByteOffset]] 。
15. 如果 targetOffset = +∞,则抛出
RangeError 异常。
16. 如果 srcLength + targetOffset >
targetLength ,则抛出 RangeError 异常。
17. 如果 target .[[ContentType]]
与 source .[[ContentType]] 不相同,则抛出 TypeError
异常。
18. 如果 IsSharedArrayBuffer (srcBuffer )
为 true ,且 IsSharedArrayBuffer (targetBuffer )
为 true ,且 srcBuffer .[[ArrayBufferData]] 与
targetBuffer .[[ArrayBufferData]] 相同,则设定
sameSharedArrayBuffer 为 true ;否则,
设定 sameSharedArrayBuffer 为 false 。
19. 如果 SameValue (srcBuffer ,
targetBuffer ) 为 true 或 sameSharedArrayBuffer 为
true ,则
a. 设定 srcByteLength 为 TypedArrayByteLength (srcRecord )。
b. 将 srcBuffer 设定为 ? CloneArrayBuffer (srcBuffer ,
srcByteOffset , srcByteLength )。
c. 设定 srcByteIndex 为 0。
20. 否则,
a. 设定 srcByteIndex 为 srcByteOffset 。
21. 设定 targetByteIndex 为(targetOffset ×
targetElementSize ) + targetByteOffset 。
22. 设定 limit 为 targetByteIndex
+(targetElementSize × srcLength )。
23. 如果 srcType 为 targetType ,则
a. 注意:传输必须以保留源数据的位级编码的方式进行。
b. 重复以下操作,直到 targetByteIndex
< limit ,
i. 设定 value 为 GetValueFromBuffer (srcBuffer ,
srcByteIndex , uint8 , true ,
unordered )。
ii. 执行 SetValueInBuffer (targetBuffer ,
targetByteIndex , uint8 , value ,
true , unordered )。
iii. 将 srcByteIndex 设定为
srcByteIndex + 1。
iv. 将 targetByteIndex 设定为
targetByteIndex + 1。
24. 否则,
a. 重复以下操作,直到 targetByteIndex
< limit ,
i. 设定 value 为 GetValueFromBuffer (srcBuffer ,
srcByteIndex , srcType , true ,
unordered )。
ii. 执行 SetValueInBuffer (targetBuffer ,
targetByteIndex , targetType , value ,
true , unordered )。
iii. 将 srcByteIndex 设定为
srcByteIndex + srcElementSize 。
iv. 将 targetByteIndex 设定为
targetByteIndex + targetElementSize 。
25. 返回 unused 。
23.2.3.26.2 SetTypedArrayFromArrayLike ( target ,
targetOffset , source )
抽象操作 SetTypedArrayFromArrayLike 接受以下参数:target (一个 TypedArray )、targetOffset (一个非负的
整数
或 +∞),以及 source (一个 ECMAScript 语言值 ,但不是一个
TypedArray ),并返回一个 正常完成记录 (包含
unused )或一个 抛出完成记录 。它在
target 中设置多个值,从 targetOffset 开始,值从 source 中读取。调用时执行以下步骤:
1. 设定 targetRecord 为 MakeTypedArrayWithBufferWitnessRecord (target ,
seq-cst )。
2. 如果 IsTypedArrayOutOfBounds (targetRecord )
为 true ,则抛出 TypeError 异常。
3. 设定 targetLength 为 TypedArrayLength (targetRecord )。
4. 设定 src 为 ? ToObject (source )。
5. 设定 srcLength 为 ? LengthOfArrayLike (src )。
6. 如果 targetOffset = +∞,则抛出
RangeError 异常。
7. 如果 srcLength + targetOffset >
targetLength ,则抛出 RangeError 异常。
8. 设定 k 为 0。
9. 重复以下操作,直到 k
< srcLength ,
a. 设定 Pk 为 ! ToString (𝔽 (k ))。
b. 设定 value 为 ? Get (src , Pk )。
c. 设定 targetIndex 为 𝔽 (targetOffset +
k )。
d. 执行 ? TypedArraySetElement (target ,
targetIndex , value )。
e. 将 k 设定为 k + 1。
10. 返回 unused 。
23.2.3.27 %TypedArray%.prototype.slice ( start ,
end
)
该方法的参数解释和使用方式与 Array.prototype.slice
相同,如 23.1.3.28
所定义。
当调用该方法时,执行以下步骤:
1. 让 O 成为 this 值。
2. 让 taRecord 为 ? ValidateTypedArray (O ,
seq-cst ).
3. 让 srcArrayLength 为 TypedArrayLength (taRecord ).
4. 让 relativeStart 为 ? ToIntegerOrInfinity (start ).
5. 如果 relativeStart = -∞,则让 startIndex
为 0。
6. 否则如果 relativeStart < 0,则让 startIndex 为
max (srcArrayLength +
relativeStart , 0)。
7. 否则,让 startIndex 为 min (relativeStart ,
srcArrayLength )。
8. 如果 end 为 undefined ,则让
relativeEnd 为 srcArrayLength ; 否则让 relativeEnd 为 ? ToIntegerOrInfinity (end )。
9. 如果 relativeEnd = -∞,则让 endIndex 为 0。
10. 否则如果 relativeEnd < 0,则让 endIndex
为 max (srcArrayLength +
relativeEnd , 0)。
11. 否则,让 endIndex 为 min (relativeEnd ,
srcArrayLength )。
12. 让 countBytes 为 max (endIndex
-
startIndex , 0)。
13. 让 A 为 ? TypedArraySpeciesCreate (O , « 𝔽 (countBytes ) »)。
14. 如果 countBytes > 0,则
a. 将 taRecord 设置为 MakeTypedArrayWithBufferWitnessRecord (O ,
seq-cst ).
b. 如果 IsTypedArrayOutOfBounds (taRecord )
为 true ,则抛出 TypeError 异常。
c. 将 endIndex 设置为 min (endIndex , TypedArrayLength (taRecord ))。
d. 将 countBytes 设置为 max (endIndex -
startIndex , 0)。
e. 让 srcType 为 TypedArrayElementType (O )。
f. 让 targetType 为 TypedArrayElementType (A )。
g. 如果 srcType 为 targetType ,则
i. 注意:传输必须以保持源数据的位级编码的方式进行。
ii. 让 srcBuffer 为 O .[[ViewedArrayBuffer]] 。
iii. 让 targetBuffer 为 A .[[ViewedArrayBuffer]] 。
iv. 让 elementSize 为 TypedArrayElementSize (O )。
v. 让 srcByteOffset 为 O .[[ByteOffset]] 。
vi. 让 srcByteIndex 为
(startIndex
×
elementSize ) + srcByteOffset 。
vii. 让 targetByteIndex 为 A .[[ByteOffset]] 。
viii. 让 endByteIndex 为
targetByteIndex + (countBytes × elementSize )。
ix. 重复,直到 targetByteIndex <
endByteIndex ,
1. 让 value 为 GetValueFromBuffer (srcBuffer ,
srcByteIndex , uint8 , true ,
unordered ).
2. 执行 SetValueInBuffer (targetBuffer ,
targetByteIndex , uint8 , value ,
true , unordered ).
3. 将 srcByteIndex 设置为
srcByteIndex + 1。
4. 将 targetByteIndex 设置为
targetByteIndex + 1。
h. 否则,
i. 让 n 为 0。
ii. 让 k 为 startIndex 。
iii. 重复,直到 k <
endIndex ,
1. 让 Pk 为 ! ToString (𝔽 (k )).
2. 让 kValue 为 ! Get (O ,
Pk ).
3. 执行 ! Set (A ,
! ToString (𝔽 (n )),
kValue , true ).
4. 将 k 设置为 k + 1。
5. 将 n 设置为 n + 1。
15. 返回 A 。
该方法不是通用的。this 值必须是具有 [[TypedArrayName]] 内部槽的对象。
23.2.3.28 %TypedArray%.prototype.some ( callbackfn [ ,
thisArg ] )
该方法的参数解释和使用方式与 Array.prototype.some
相同,如 23.1.3.29 所定义。
调用该方法时,执行以下步骤:
1. 让 O 成为 this 值。
2. 让 taRecord 为 ? ValidateTypedArray (O ,
seq-cst ).
3. 让 len 为 TypedArrayLength (taRecord ).
4. 如果 IsCallable (callbackfn )
为 false ,则抛出 TypeError 异常。
5. 让 k 为 0。
6. 重复,直到 k < len ,
a. 让 Pk 为 ! ToString (𝔽 (k )).
b. 让 kValue 为 ! Get (O ,
Pk ).
c. 让 testResult 为 ToBoolean (?
Call (callbackfn , thisArg , «
kValue , 𝔽 (k ),
O »)).
d. 如果 testResult 为 true ,
则返回
true 。
e. 将 k 设置为 k + 1。
7. 返回 false 。
该方法不是通用的。this 值必须是具有 [[TypedArrayName]] 内部槽的对象。
23.2.3.29 %TypedArray%.prototype.sort ( comparefn )
这是一个独立的方法,除非下面有所描述,否则实现的要求与 Array.prototype.sort
相同,如 23.1.3.30 所定义。该方法的实现可以优化,因为
this 值是一个固定长度的对象,并且其 整数索引
属性不为稀疏。
该方法不是通用的。this 值必须是具有 [[TypedArrayName]] 内部槽的对象。
调用时执行以下步骤:
1. 如果 comparefn 不为 undefined 且
IsCallable (comparefn )
为 false ,则抛出 TypeError 异常。
2. 让 obj 为 this 值。
3. 让 taRecord 为 ? ValidateTypedArray (obj ,
seq-cst ).
4. 让 len 为 TypedArrayLength (taRecord ).
5. 注意:以下闭包执行的是数值比较,而不是 23.1.3.30
中使用的字符串比较。
6. 让 SortCompare 为一个新的 抽象闭包 ,具有参数 (x ,
y ),捕获 comparefn 并执行以下步骤:
a. 返回 ? CompareTypedArrayElements (x ,
y , comparefn ).
7. 让 sortedList 为 ? SortIndexedProperties (obj , len ,
SortCompare , read-through-holes ).
8. 让 j 为 0。
9. 重复,直到 j < len ,
a. 执行 ! Set (obj ,
! ToString (𝔽 (j )),
sortedList [j ], true ).
b. 将 j 设置为 j + 1。
10. 返回 obj 。
注
由于 NaN 总是比较大于任何其他值(见 CompareTypedArrayElements ),
NaN 属性值在未提供 comparefn 时总是排序到结果的末尾。
23.2.3.30 %TypedArray%.prototype.subarray ( start ,
end
)
此方法返回一个新的 TypedArray ,其元素类型与当前 TypedArray 的元素类型相同,且其 ArrayBuffer 与当前
TypedArray 的 ArrayBuffer 相同,
引用从 start (含)到 end (不含)之间的元素。如果 start 或 end
为负值,则表示从数组末尾的索引,而不是从开头。
调用时执行以下步骤:
1. 让 O 为 this 值。
2. 执行 ? RequireInternalSlot (O ,
[[TypedArrayName]] ).
3. Assert :O 具有 [[ViewedArrayBuffer]] 内部槽。
4. 让 buffer 为 O .[[ViewedArrayBuffer]] 。
5. 让 srcRecord 为 MakeTypedArrayWithBufferWitnessRecord (O ,
seq-cst ).
6. 如果 IsTypedArrayOutOfBounds (srcRecord )
为 true ,则
a. 让 srcLength 为 0。
7. 否则,
a. 让 srcLength 为 TypedArrayLength (srcRecord ).
8. 让 relativeStart 为 ? ToIntegerOrInfinity (start ).
9. 如果 relativeStart = -∞,让 startIndex
为
0。
10. 否则,如果 relativeStart < 0,则让
startIndex 为 max (srcLength +
relativeStart , 0)。
11. 否则,令 startIndex 为 min (relativeStart ,
srcLength )。
12. 让 elementSize 为 TypedArrayElementSize (O ).
13. 让 srcByteOffset 为 O .[[ByteOffset]] 。
14. 让 beginByteOffset 为 srcByteOffset +
(startIndex × elementSize )。
15. 如果 O .[[ArrayLength]] 为
auto 且 end 为 undefined ,则
a. 让 argumentsList 为 « buffer ,
𝔽 (beginByteOffset ) ».
16. 否则,
a. 如果 end 为 undefined ,则让
relativeEnd 为 srcLength ;否则让 relativeEnd 为
? ToIntegerOrInfinity (end )。
b. 如果 relativeEnd = -∞,让 endIndex
为
0。
c. 否则,如果 relativeEnd < 0,则让
endIndex 为 max (srcLength +
relativeEnd , 0)。
d. 否则,令 endIndex 为 min (relativeEnd ,
srcLength )。
e. 让 newLength 为 max (endIndex -
startIndex , 0)。
f. 让 argumentsList 为 « buffer ,
𝔽 (beginByteOffset ),
𝔽 (newLength ) ».
17. 返回 ? TypedArraySpeciesCreate (O ,
argumentsList ).
此方法并非通用方法。this 值必须是具有 [[TypedArrayName]] 内部槽的对象。
23.2.3.31 %TypedArray%.prototype.toLocaleString ( [ reserved1
[
,
reserved2 ] ] )
这是一个独立的方法,其实现与 Array.prototype.toLocaleString
相同,正如在 23.1.3.32 中定义的那样,
不同之处在于,调用了 TypedArrayLength ,而不是执行 [[Get]] 操作以获取 "length" 。算法的实现可以通过知道 this
值具有固定长度(当底层缓冲区不可调整且 integer-indexed
属性不稀疏时)进行优化。然而,这种优化不得引入算法指定行为的任何可观察变化。
此方法并非通用方法。ValidateTypedArray
在评估算法之前被调用,使用 this 值和 seq-cst 作为参数。如果结果是 abrupt
completion ,则抛出该异常,而不是评估算法。
注
如果 ECMAScript 实现包括 ECMA-402 国际化 API,则此方法基于 ECMA-402 规范中 Array.prototype.toLocaleString
的算法。
23.2.3.32 %TypedArray%.prototype.toReversed ( )
此方法在调用时执行以下步骤:
1. 让 O 成为 this 值。
2. 让 taRecord 为 ? ValidateTypedArray (O ,
seq-cst ).
3. 让 length 为 TypedArrayLength (taRecord ).
4. 让 A 为 ? TypedArrayCreateSameType (O , « 𝔽 (length ) »).
5. 让 k 为 0。
6. 重复执行,直到 k < length ,
a. 让 from 为 ! ToString (𝔽 (length -
k - 1)).
b. 让 Pk 为 ! ToString (𝔽 (k )).
c. 让 fromValue 为 ! Get (O ,
from ).
d. 执行 ! Set (A ,
Pk , fromValue , true ).
e. 将 k 设置为 k + 1。
7. 返回 A 。
23.2.3.33 %TypedArray%.prototype.toSorted ( comparefn )
此方法在调用时执行以下步骤:
1. 如果 comparefn 不是 undefined 且
IsCallable (comparefn )
为 false ,则抛出一个 TypeError 异常。
2. 让 O 成为 this 值。
3. 让 taRecord 为 ? ValidateTypedArray (O ,
seq-cst ).
4. 让 len 为 TypedArrayLength (taRecord ).
5. 让 A 为 ? TypedArrayCreateSameType (O , « 𝔽 (len ) »).
6. 注意:以下闭包执行的是数字比较,而不是在 23.1.3.34 中使用的字符串比较。
7. 让 SortCompare 成为一个新的 Abstract Closure ,其参数为
(x , y ),捕获 comparefn 并在调用时执行以下步骤:
a. 返回 ? CompareTypedArrayElements (x ,
y , comparefn ).
8. 让 sortedList 为 ? SortIndexedProperties (O , len ,
SortCompare , read-through-holes ).
9. 让 j 为 0。
10. 重复执行,直到 j < len ,
a. 执行 ! Set (A ,
! ToString (𝔽 (j )),
sortedList [j ], true ).
b. 将 j 设置为 j + 1。
11. 返回 A 。
23.2.3.34 %TypedArray%.prototype.toString ( )
属性 "toString" 的初始值是 %Array.prototype.toString%,
定义在
23.1.3.36 。
23.2.3.35 %TypedArray%.prototype.values ( )
此方法在调用时执行以下步骤:
1. 让 O 为 this 值。
2. 执行 ? ValidateTypedArray (O ,
seq-cst ).
3. 返回 CreateArrayIterator (O ,
value ).
23.2.3.36 %TypedArray%.prototype.with ( index ,
value
)
此方法在调用时执行以下步骤:
1. 让 O 为 this 值。
2. 让 taRecord 为 ? ValidateTypedArray (O ,
seq-cst ).
3. 让 len 为 TypedArrayLength (taRecord ).
4. 让 relativeIndex 为 ? ToIntegerOrInfinity (index ).
5. 如果 relativeIndex ≥ 0,则让 actualIndex
为
relativeIndex 。
6. 否则,让 actualIndex 为 len +
relativeIndex 。
7. 如果 O .[[ContentType]] 是
bigint ,则让 numericValue 为 ? ToBigInt (value ).
8. 否则,让 numericValue 为 ? ToNumber (value ).
9. 如果 IsValidIntegerIndex (O ,
𝔽 (actualIndex )) 为
false ,则抛出 RangeError 异常。
10. 让 A 为 ? TypedArrayCreateSameType (O , « 𝔽 (len ) »).
11. 让 k 为 0。
12. 重复执行,直到 k
< len ,
a. 让 Pk 为 ! ToString (𝔽 (k )).
b. 如果 k 为 actualIndex ,则让
fromValue 为 numericValue 。
c. 否则,让 fromValue 为 ! Get (O ,
Pk ).
d. 执行 ! Set (A ,
Pk , fromValue , true ).
e. 将 k 设置为 k + 1。
13. 返回 A 。
23.2.3.37 %TypedArray%.prototype [ @@iterator ] ( )
@@iterator 属性的初始值是
%TypedArray.prototype.values%,定义在 23.2.3.35 。
23.2.3.38 获取 %TypedArray%.prototype [ @@toStringTag ]
%TypedArray% .prototype[@@toStringTag]
是一个 访问器属性 ,其设置
访问器函数为 undefined 。其获取
访问器函数在调用时执行以下步骤:
1. 令 O 为 this 值。
2. 如果 O 不是一个对象 ,返回
undefined 。
3. 如果 O 没有 [[TypedArrayName]]
内部槽,返回 undefined 。
4. 令 name 为 O .[[TypedArrayName]] 。
5. 断言 : name 是一个字符串 。
6. 返回 name 。
该属性的特性是 { [[Enumerable]] : false ,
[[Configurable]] : true }。
该函数的 "name" 属性的初始值是 "get
[Symbol.toStringTag]" 。
23.2.4 TypedArray 对象的抽象操作
23.2.4.1 TypedArraySpeciesCreate ( exemplar ,
argumentList )
抽象操作 TypedArraySpeciesCreate 接受参数 exemplar (一个 TypedArray )和 argumentList
(一个 列表 的
ECMAScript 语言值 ),并返回一个
正常完成包含 的
TypedArray 或一个 抛出完成 。它用于指定使用从
exemplar 派生的 构造函数 创建新的 TypedArray 。与可以通过使用
@@species 创建非数组对象的 ArraySpeciesCreate 不同,
此操作强制要求构造函数创建一个实际的 TypedArray 。它在调用时执行以下步骤:
1. 让 defaultConstructor 为与 构造函数 名称
exemplar .[[TypedArrayName]] 相关联的固有对象,在 表 71 中。
2. 让 constructor 为 ? SpeciesConstructor (exemplar ,
defaultConstructor ).
3. 让 result 为 ? TypedArrayCreateFromConstructor (constructor ,
argumentList ).
4. 断言 : result 具有 [[TypedArrayName]] 和 [[ContentType]] 内部槽。
5. 如果 result .[[ContentType]]
不是 exemplar .[[ContentType]] ,则抛出 TypeError 异常。
6. 返回 result 。
23.2.4.2 TypedArrayCreateFromConstructor ( constructor ,
argumentList )
抽象操作 TypedArrayCreateFromConstructor 接受参数 constructor (一个 构造函数 )和
argumentList
(一个 列表 的
ECMAScript 语言值 ),并返回一个
正常完成包含 的
TypedArray 或一个 抛出完成 。它用于指定使用
构造函数 函数创建新的 TypedArray 。它在调用时执行以下步骤:
1. 让 newTypedArray 为 ? 构造 (constructor , argumentList ).
2. 让 taRecord 为 ? 验证TypedArray (newTypedArray ,
seq-cst ).
3. 如果 argumentList 中的元素数量为 1 并且
argumentList [0] 是
一个数字 ,则
a. 如果 IsTypedArrayOutOfBounds (taRecord )
为 true ,则抛出 TypeError 异常。
b. 让 length 为 TypedArrayLength (taRecord ).
c. 如果 length < ℝ (argumentList [0]),
抛出 TypeError 异常。
4. 返回 newTypedArray 。
23.2.4.3 TypedArrayCreateSameType ( exemplar ,
argumentList )
抽象操作 TypedArrayCreateSameType 接受参数 exemplar (一个 TypedArray )和 argumentList
(一个 列表 的
ECMAScript 语言值 ),并返回一个
正常完成包含 的
TypedArray 或一个 抛出完成 。它用于指定使用从
exemplar 派生的 构造函数 函数创建新的 TypedArray 。与 TypedArraySpeciesCreate
不同,后者可以通过使用 @@species 构造自定义 TypedArray 子类,此操作始终使用内置的 TypedArray 构造函数 。它在调用时执行以下步骤:
1. 让 constructor 为与 构造函数 名称
exemplar .[[TypedArrayName]] 相关联的内在对象
在 表 71 中。
2. 让 result 为 ? TypedArrayCreateFromConstructor (constructor ,
argumentList ).
3. 断言 : result 具有 [[TypedArrayName]] 和 [[ContentType]] 内部槽。
4. 断言 : result .[[ContentType]] 是 exemplar .[[ContentType]] 。
5. 返回 result 。
23.2.4.4 ValidateTypedArray ( O , order )
抽象操作 ValidateTypedArray 接受参数 O (一个 ECMAScript
语言值 )和 order (seq-cst 或
unordered ),并返回一个 正常完成包含 的
带缓冲区见证记录的
TypedArray 或一个 抛出完成 。它在调用时执行以下步骤:
1. 执行 ? RequireInternalSlot (O ,
[[TypedArrayName]] ).
2. 断言 : O 具有一个 [[ViewedArrayBuffer]] 内部槽。
3. 让 taRecord 为 MakeTypedArrayWithBufferWitnessRecord (O ,
order ).
4. 如果 IsTypedArrayOutOfBounds (taRecord )
为 true ,抛出一个 TypeError 异常。
5. 返回 taRecord 。
23.2.4.5 TypedArrayElementSize ( O )
抽象操作 TypedArrayElementSize 接受参数 O (一个 TypedArray )并返回一个非负的 整数 。它在调用时执行以下步骤:
1. 返回在 表
71 中为
O .[[TypedArrayName]] 指定的元素大小值。
23.2.4.6 TypedArrayElementType ( O )
抽象操作 TypedArrayElementType 接受参数 O (一个 TypedArray )并返回一个 TypedArray 元素类型 。它在调用时执行以下步骤:
1. 返回在 表
71 中为
O .[[TypedArrayName]] 指定的元素类型值。
23.2.4.7 CompareTypedArrayElements ( x , y ,
comparefn )
抽象操作 CompareTypedArrayElements 接受参数 x (一个 Number 或 BigInt)、y (一个 Number 或 BigInt)和
comparefn (一个 函数对象 或
undefined ),并返回一个 正常完成 的 Number
或一个 突发完成 。它在调用时执行以下步骤:
1. 断言 : x 是一个
Number 并且 y 是一个
Number ,或 x 是一个
BigInt 并且 y 是一个
BigInt 。
2. 如果 comparefn 不是 undefined ,则
a. 让 v 为 ? ToNumber (? Call (comparefn ,
undefined ,
«
x , y »))。
b. 如果 v 是 NaN ,返回
+0 𝔽 。
c. 返回 v 。
3. 如果 x 和 y 都是 NaN ,
返回 +0 𝔽 。
4. 如果 x 是 NaN ,返回
1 𝔽 。
5. 如果 y 是 NaN ,返回
-1 𝔽 。
6. 如果 x < y ,返回
-1 𝔽 。
7. 如果 x > y ,返回
1 𝔽 。
8. 如果 x 是 -0 𝔽 并且
y 是 +0 𝔽 ,返回 -1 𝔽 。
9. 如果 x 是 +0 𝔽 并且
y 是 -0 𝔽 ,返回 1 𝔽 。
10. 返回 +0 𝔽 。
注
这执行的是数字比较,而不是在
23.1.3.30.2 中使用的字符串比较。
23.2.5 TypedArray 构造函数
每个 TypedArray 构造函数 :
是一个内部对象,其结构如下所述,只是使用的名称与 构造函数 的名称不同,在 表71 中。
是一个函数,其行为根据参数的数量和类型而不同。对 TypedArray 的实际调用行为取决于传递给它的参数的数量和种类。
不打算作为函数调用,并且当以这种方式调用时会抛出异常。
可以用作类定义的 extends
子句的值。意图继承指定 TypedArray 行为的子类 构造函数 必须包括对
TypedArray 构造函数 的 super
调用,以创建和初始化子类实例,使其具备支持 %TypedArray% .prototype
内建方法所需的内部状态。
23.2.5.1 TypedArray ( ...args )
每个 TypedArray 构造函数 在被调用时执行以下步骤:
1. 如果 NewTarget 是 undefined ,抛出
TypeError 异常。
2. 令 constructorName 为在 构造函数 中指定的
TypedArray 构造函数的名称值的字符串值,如 表
71 所示。
3. 令 proto 为
"%TypedArray .prototype%"
。
4. 令 numberOfArgs 为 args 中的元素个数。
5. 如果 numberOfArgs = 0,则
a. 返回 ? AllocateTypedArray (constructorName , NewTarget,
proto , 0)。
6. 否则,
a. 令 firstArgument 为 args [0]。
b. 如果 firstArgument 是一个对象 ,则
i. 令 O 为 ? AllocateTypedArray (constructorName ,
NewTarget, proto )。
ii. 如果 firstArgument 具有 [[TypedArrayName]] 内部槽,则
1. 执行 ? InitializeTypedArrayFromTypedArray (O ,
firstArgument )。
iii. 否则,如果 firstArgument 具有 [[ArrayBufferData]] 内部槽,则
1. 如果 numberOfArgs > 1,令
byteOffset 为 args [1];否则令 byteOffset 为
undefined 。
2. 如果 numberOfArgs > 2,令 length 为
args [2];否则令 length 为 undefined 。
3. 执行 ? InitializeTypedArrayFromArrayBuffer (O ,
firstArgument , byteOffset , length )。
iv. 否则,
1. 断言 :firstArgument
是一个对象 ,且
firstArgument 既没有 [[TypedArrayName]] 内部槽也没有 [[ArrayBufferData]] 内部槽。
2. 令 usingIterator 为 ? GetMethod (firstArgument , @@iterator )。
3. 如果 usingIterator 不为
undefined ,则
a. 令 values 为 ? IteratorToList (? GetIteratorFromMethod (firstArgument ,
usingIterator ))。
b. 执行 ? InitializeTypedArrayFromList (O ,
values )。
4. 否则,
a. 注意:firstArgument 不是一个可迭代对象,因此假设它已经是一个
类数组对象 。
b. 执行 ? InitializeTypedArrayFromArrayLike (O ,
firstArgument )。
v. 返回 O 。
c. 否则,
i. 断言 :firstArgument
不是一个对象 。
ii. 令 elementLength 为 ? ToIndex (firstArgument )。
iii. 返回 ? AllocateTypedArray (constructorName ,
NewTarget, proto , elementLength )。
23.2.5.1.1 AllocateTypedArray ( constructorName ,
newTarget , defaultProto [ , length ] )
抽象操作 AllocateTypedArray 接受以下参数:constructorName (一个字符串,表示 TypedArray 构造函数 在
表 71 中的名称),
newTarget (一个 构造函数 ),以及
defaultProto (一个字符串)和可选参数 length (一个非负 整数 ),
并返回一个 正常完成 ,
包含一个 TypedArray 或一个 抛出完成 。
它用于验证并创建一个 TypedArray 构造函数 的实例。
如果提供了 length 参数,还会分配一个该长度的 ArrayBuffer,并与新创建的 TypedArray
实例相关联。AllocateTypedArray 提供了 TypedArray 使用的通用语义。调用时执行以下步骤:
1. 令 proto 为 ? GetPrototypeFromConstructor (newTarget ,
defaultProto ).
2. 令 obj 为 TypedArrayCreate (proto ).
3. Assert :obj .[[ViewedArrayBuffer]] 为 undefined 。
4. 将 obj .[[TypedArrayName]]
设置为 constructorName 。
5. 如果 constructorName 为
"BigInt64Array" 或
"BigUint64Array" ,则将 obj .[[ContentType]] 设置为
bigint 。
6. 否则,将 obj .[[ContentType]]
设置为 number 。
7. 如果 length 不存在,则
a. 将 obj .[[ByteLength]]
设置为 0。
b. 将 obj .[[ByteOffset]]
设置为 0。
c. 将 obj .[[ArrayLength]]
设置为 0。
8. 否则,
a. 执行 ? AllocateTypedArrayBuffer (obj ,
length ).
9. 返回 obj 。
23.2.5.1.2 初始化TypedArray从TypedArray( O ,
srcArray )
抽象操作初始化TypedArray从TypedArray接受参数 O (一个 TypedArray )和 srcArray
(一个 TypedArray )并返回一个
正常完成
包含 unused 或一个 抛出
完成 。它在调用时执行以下步骤:
1. 让 srcData 为 srcArray .[[ViewedArrayBuffer]] 。
2. 让 elementType 为 TypedArrayElementType (O ).
3. 让 elementSize 为 TypedArrayElementSize (O ).
4. 让 srcType 为 TypedArrayElementType (srcArray ).
5. 让 srcElementSize 为 TypedArrayElementSize (srcArray ).
6. 让 srcByteOffset 为 srcArray .[[ByteOffset]] 。
7. 让 srcRecord 为 MakeTypedArrayWithBufferWitnessRecord (srcArray ,
seq-cst ).
8. 如果 IsTypedArrayOutOfBounds (srcRecord )
为 true ,则抛出一个 TypeError 异常。
9. 让 elementLength 为 TypedArrayLength (srcRecord ).
10. 让 byteLength 为 elementSize ×
elementLength 。
11. 如果 elementType 等于 srcType ,则
a. 让 data 为 ? CloneArrayBuffer (srcData ,
srcByteOffset , byteLength ).
12. 否则,
a. 让 data 为 ? AllocateArrayBuffer (%ArrayBuffer% ,
byteLength ).
b. 如果 srcArray .[[ContentType]] 不等于 O .[[ContentType]] ,则抛出一个 TypeError 异常。
c. 让 srcByteIndex 为
srcByteOffset 。
d. 让 targetByteIndex 为 0。
e. 让 count 为 elementLength 。
f. 重复,直到 count > 0,
i. 让 value 为 GetValueFromBuffer (srcData ,
srcByteIndex , srcType , true ,
unordered ).
ii. 执行 SetValueInBuffer (data ,
targetByteIndex , elementType , value ,
true , unordered ).
iii. 将 srcByteIndex 设置为
srcByteIndex + srcElementSize 。
iv. 将 targetByteIndex 设置为
targetByteIndex + elementSize 。
v. 将 count 设置为 count - 1。
13. 将 O .[[ViewedArrayBuffer]]
设置为 data 。
14. 将 O .[[ByteLength]]
设置为
byteLength 。
15. 将 O .[[ByteOffset]]
设置为
0。
16. 将 O .[[ArrayLength]]
设置为
elementLength 。
17. 返回 unused 。
23.2.5.1.3 InitializeTypedArrayFromArrayBuffer ( O ,
buffer , byteOffset , length )
抽象操作 InitializeTypedArrayFromArrayBuffer 接受参数 O (一个
TypedArray )、buffer (一个
ArrayBuffer 或 SharedArrayBuffer)、byteOffset (一个 ECMAScript 语言值 ),以及
length (一个 ECMAScript
语言值 ),并返回一个 正常完成 ,包含
unused ,或者一个 抛出完成 。它在被调用时执行以下步骤:
1. 设定 elementSize 为 TypedArrayElementSize (O )。
2. 设定 offset 为 ? ToIndex (byteOffset )。
3. 如果 offset 模
elementSize ≠ 0,则抛出一个 RangeError 异常。
4. 设定 bufferIsFixedLength 为 IsFixedLengthArrayBuffer (buffer )。
5. 如果 length 不是 undefined ,则
a. 设定 newLength 为 ? ToIndex (length )。
6. 如果 IsDetachedBuffer (buffer )
为 true ,则抛出一个 TypeError 异常。
7. 设定 bufferByteLength 为 ArrayBufferByteLength (buffer ,
seq-cst ).
8. 如果 length 为 undefined 且
bufferIsFixedLength 为 false ,则
a. 如果 offset > bufferByteLength ,则抛出一个
RangeError 异常。
b. 将 O .[[ByteLength]]
设为 auto 。
c. 将 O .[[ArrayLength]]
设为 auto 。
9. 否则,
a. 如果 length 为 undefined ,则
i. 如果 bufferByteLength 模
elementSize ≠ 0,则抛出一个 RangeError 异常。
ii. 设定 newByteLength 为
bufferByteLength - offset 。
iii. 如果 newByteLength < 0,则抛出一个
RangeError 异常。
b. 否则,
i. 设定 newByteLength 为
newLength
×
elementSize 。
ii. 如果 offset + newByteLength
>
bufferByteLength ,则抛出一个 RangeError 异常。
c. 将 O .[[ByteLength]]
设为
newByteLength 。
d. 将 O .[[ArrayLength]]
设为 newByteLength / elementSize 。
10. 将 O .[[ViewedArrayBuffer]]
设为 buffer 。
11. 将 O .[[ByteOffset]]
设为
offset 。
12. 返回 unused 。
23.2.5.1.4 InitializeTypedArrayFromList ( O ,
values
)
抽象操作 InitializeTypedArrayFromList 接受参数 O (一个 TypedArray )和 values (一个
列表 ,包含
ECMAScript 语言值 ),并返回一个
正常完成 ,包含
unused ,或者一个 抛出完成 。它在被调用时执行以下步骤:
1. 设定 len 为 values 中元素的数量。
2. 执行 ? AllocateTypedArrayBuffer (O ,
len )。
3. 设定 k 为 0。
4. 重复,直到 k < len ,
a. 设定 Pk 为 ! ToString (𝔽 (k )).
b. 设定 kValue 为 values 的第一个元素。
c. 从 values 中移除第一个元素。
d. 执行 ? Set (O , Pk , kValue ,
true ).
e. 将 k 设为 k + 1。
5. Assert :values 现在是一个空的
列表 。
6. 返回 unused 。
23.2.5.1.5 InitializeTypedArrayFromArrayLike ( O ,
arrayLike )
抽象操作 InitializeTypedArrayFromArrayLike 接受参数 O (一个 TypedArray )和
arrayLike
(一个对象,但不是 TypedArray 或 ArrayBuffer)并返回一个 正常完成 ,包含
unused ,或者一个 抛出完成 。它在被调用时执行以下步骤:
1. 设定 len 为 ? LengthOfArrayLike (arrayLike ).
2. 执行 ? AllocateTypedArrayBuffer (O ,
len )。
3. 设定 k 为 0。
4. 重复,直到 k < len ,
a. 设定 Pk 为 ! ToString (𝔽 (k )).
b. 设定 kValue 为 ? Get (arrayLike , Pk ).
c. 执行 ? Set (O , Pk , kValue ,
true ).
d. 将 k 设为 k + 1。
5. 返回 unused 。
23.2.5.1.6 AllocateTypedArrayBuffer ( O , length
)
抽象操作 AllocateTypedArrayBuffer 接受参数 O (一个 TypedArray )和 length (一个非负的
整数 )并返回一个 正常完成 ,包含
unused ,或者一个 抛出完成 。它为
O 分配并关联一个 ArrayBuffer。它在被调用时执行以下步骤:
1. Assert : O .[[ViewedArrayBuffer]] 是 undefined 。
2. 设定 elementSize 为 TypedArrayElementSize (O ).
3. 设定 byteLength 为 elementSize ×
length 。
4. 设定 data 为 ? AllocateArrayBuffer (%ArrayBuffer% ,
byteLength ).
5. 将 O .[[ViewedArrayBuffer]]
设为 data 。
6. 将 O .[[ByteLength]] 设为
byteLength 。
7. 将 O .[[ByteOffset]] 设为
0。
8. 将 O .[[ArrayLength]]
设为
length 。
9. 返回 unused 。
23.2.6 属性 TypedArray 构造器
每一个 TypedArray 构造器 :
具有一个内部插槽 [[Prototype]] ,其值为 %TypedArray% 。
具有一个属性 "length" ,其值为 3 𝔽 。
具有一个属性 "name" ,其值为在 构造器 中指定的构造器名称的字符串值,见 表 71 。
具有以下属性:
23.2.6.1 TypedArray .BYTES_PER_ELEMENT
TypedArray .BYTES_PER_ELEMENT
的值是 表71 中为
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
的值是 表71 中为
TypedArray 指定的元素大小值。
该属性的特性为 { [[Writable]] : false ,
[[Enumerable]] : false , [[Configurable]] : false }。
23.2.7.2 TypedArray .prototype.constructor
给定 TypedArray 的原型的 "constructor" 属性的初始值是 构造函数 本身。
23.2.8 TypedArray 实例的属性
TypedArray 实例是 TypedArrays 。每个 TypedArray
实例从对应的 TypedArray 原型对象继承属性。每个 TypedArray 实例具有以下内部槽:[[TypedArrayName]] 、[[ViewedArrayBuffer]] 、[[ByteLength]] 、[[ByteOffset]] 和 [[ArrayLength]] 。
24 键集合
24.1 Map 对象
Map 是键/值对的集合,其中键和值都可以是任意的 ECMAScript 语言值 。在 Map
的集合中,一个独特的键值只能出现在一个键/值对中。使用 SameValueZero
比较算法来区分独特的键值。
Map 必须使用哈希表或其他机制来实现,这些机制平均提供对集合中元素数量的次线性访问时间。本规范中使用的数据结构仅用于描述 Map 的所需可观察语义,不打算作为可行的实现模型。
24.1.1 Map 构造函数
Map 构造函数 :
是 %Map% 。
是 全局对象 的 "Map"
属性的初始值。
在作为 构造函数 调用时创建并初始化一个新的 Map。
不应作为函数调用,如果以该方式调用将会抛出异常。
可以在类定义的 extends
子句中用作值。打算继承指定 Map 行为的子类 构造函数 必须包括对 Map 构造函数
的 super
调用,以便使用内部状态创建和初始化子类实例,以支持 Map.prototype
内置方法。
24.1.1.1 Map ( [ iterable ] )
调用此函数时执行以下步骤:
1. 如果 NewTarget 是 undefined ,则抛出
TypeError 异常。
2. 令 map 为 ? OrdinaryCreateFromConstructor (NewTarget,
"%Map.prototype%" , « [[MapData]] »)。
3. 将 map .[[MapData]] 设置为一个新的空
列表 。
4. 如果 iterable 是 undefined 或
null ,则返回 map 。
5. 令 adder 为 ? Get (map , "set" )。
6. 如果 IsCallable (adder ) 是
false ,则抛出 TypeError 异常。
7. 返回 ? AddEntriesFromIterable (map , iterable ,
adder )。
注
如果参数 iterable 存在,则期望它是一个实现了 @@iterator
方法的对象,该方法返回一个迭代器对象,该迭代器对象生成一个包含两个元素的 类数组对象 ,其第一个元素是将用作 Map
键的值,第二个元素是要与该键关联的值。
24.1.1.2 AddEntriesFromIterable ( target ,
iterable ,
adder )
抽象操作 AddEntriesFromIterable 接受参数 target (一个对象)、iterable (一个 ECMAScript 语言值 ,但不能是
undefined 或 null )以及 adder (一个 函数对象 ),并返回一个包含 ECMAScript 语言值
的正常完成或一个抛出完成。adder 将被调用,其接收者为 target 。执行以下步骤:
1. 令 iteratorRecord 为 ? GetIterator (iterable ,
sync )。
2. 重复,
a. 令 next 为 ? IteratorStepValue (iteratorRecord )。
b. 如果 next 是 done ,则返回
target 。
c. 如果 next 不是对象 ,则
i. 令 error 为 ThrowCompletion (一个新创建的
TypeError 对象)。
ii. 返回 ? IteratorClose (iteratorRecord ,
error )。
d. 令 k 为 Completion (Get (next , "0" ))。
e. IfAbruptCloseIterator (k ,
iteratorRecord )。
f. 令 v 为 Completion (Get (next , "1" ))。
g. IfAbruptCloseIterator (v ,
iteratorRecord )。
h. 令 status 为 Completion (Call (adder , target , «
k ,
v »))。
i. IfAbruptCloseIterator (status ,
iteratorRecord )。
注
参数 iterable 期望是一个实现了 @@iterator
方法的对象,该方法返回一个迭代器对象,该迭代器对象生成一个包含两个元素的 类数组对象 ,其第一个元素是将用作 Map
键的值,第二个元素是要与该键关联的值。
24.1.2 Map 构造函数的属性
Map 构造函数:
24.1.2.1 Map.groupBy ( items , callbackfn )
注
callbackfn 应为一个接受两个参数的函数。 groupBy
会按升序为 items 中的每个元素调用
callbackfn 一次,并构建一个新的 Map。 callbackfn 返回的每个值都作为 Map 的键。 对于每个这样的键,结果 Map
包含一个条目,其键为该键,值为一个包含所有 callbackfn 返回该键的元素的数组。
callbackfn 将使用两个参数调用:元素的值和元素的索引。
groupBy
的返回值是一个 Map。
调用此函数时执行以下步骤:
1. 如果 NewTarget 是 undefined ,则抛出
TypeError 异常。
2. 让 groups 成为 ? GroupBy (items , callbackfn ,
zero ).
3. 让 map 成为 ! Construct (%Map% ).
4. 对于 groups 中的每个 Record
{ [[Key]] , [[Elements]] } g ,执行以下操作:
a. 让 elements 成为 CreateArrayFromList (g .[[Elements]] ).
b. 让 entry 成为 Record
{ [[Key]] : g .[[Key]] , [[Value]] : elements }。
c. 将 entry 添加到 map .[[MapData]] 中。
5. 返回 map 。
24.1.2.2 Map.prototype
Map.prototype
的初始值是 Map
原型对象 。
此属性具有属性 { [[Writable]] : false ,
[[Enumerable]] : false , [[Configurable]] :
false }。
24.1.2.3 get Map [ @@species ]
Map[@@species]
是一个 访问器属性 ,其设置访问器函数为
undefined 。
其获取访问器函数在调用时执行以下步骤:
1. 返回 this 值。
此函数的 "name" 属性值为 "get [Symbol.species]" 。
注
创建派生集合对象的方法应调用 @@species 来确定用于创建派生对象的
constructor 。子类的 constructor 可以覆盖 @@species 来更改默认的 constructor 分配。
24.1.3 Map 原型对象的属性
Map 原型对象:
24.1.3.1 Map.prototype.clear ( )
调用该方法时执行以下步骤:
1. 令 M 为 this 的值。
2. 执行 ? RequireInternalSlot (M ,
[[MapData]] )。
3. 对于 M .[[MapData]] 中的每一个
Record {
[[Key]] , [[Value]] } p ,执行以下步骤:
a. 将 p .[[Key]] 设置为
empty 。
b. 将 p .[[Value]] 设置为
empty 。
4. 返回 undefined 。
注
现有的 [[MapData]] List 将被保留,
因为可能有正在遍历该 List 的 Map
迭代器对象中断。
24.1.3.2 Map.prototype.constructor
Map.prototype.constructor
的初始值为 %Map% 。
24.1.3.3 Map.prototype.delete ( key )
调用该方法时执行以下步骤:
1. 令 M 为 this 的值。
2. 执行 ? RequireInternalSlot (M ,
[[MapData]] )。
3. 对于 M .[[MapData]] 中的每一个
Record {
[[Key]] , [[Value]] } p ,执行以下步骤:
a. 如果 p .[[Key]] 不为
empty ,
且 SameValueZero (p .[[Key]] , key ) 为 true ,则执行以下步骤:
i. 将 p .[[Key]] 设置为
empty 。
ii. 将 p .[[Value]] 设置为
empty 。
iii. 返回 true 。
4. 返回 false 。
注
使用 empty 作为规范设备,指示条目已被删除。实际实现可能会采取其他操作,如从内部数据结构中实际删除条目。
24.1.3.4 Map.prototype.entries ( )
调用该方法时执行以下步骤:
1. 令 M 为 this 的值。
2. 返回 ? CreateMapIterator (M ,
key+value )。
24.1.3.5 Map.prototype.forEach ( callbackfn [ ,
thisArg ] )
调用该方法时执行以下步骤:
1. 令 M 为 this 的值。
2. 执行 ? RequireInternalSlot (M ,
[[MapData]] )。
3. 如果 IsCallable (callbackfn )
为 false ,则抛出 TypeError 异常。
4. 令 entries 为 M .[[MapData]] 。
5. 令 numEntries 为 entries 中的元素数目。
6. 令 index 为 0。
7. 重复,当 index < numEntries 时,执行以下步骤:
a. 令 e 为 entries [index ]。
b. 将 index 设置为 index + 1。
c. 如果 e .[[Key]] 不为
empty ,
则执行以下步骤:
i. 执行 ? Call (callbackfn , thisArg , «
e .[[Value]] , e .[[Key]] , M »)。
ii. 注意:在执行 callbackfn 过程中,entries
的元素数目可能会增加。
iii. 将 numEntries 设置为 entries 的元素数目。
8. 返回 undefined 。
注
callbackfn 应该是一个接受三个参数的函数。对于 Map 中的每个键/值对,forEach
都会调用 callbackfn
一次,按照键插入的顺序。只有实际存在的 Map 键才会调用 callbackfn ;已从 Map 中删除的键不会调用。
如果提供了 thisArg 参数,则它将作为每次调用 callbackfn 的 this 值。如果没有提供,则使用
undefined 。
callbackfn 被调用时有三个参数:条目的值、条目的键和正在遍历的 Map。
forEach
不会直接改变其被调用的对象,但对象可能会被 callbackfn 的调用而改变。Map 的每个条目的 [[MapData]] 只会被访问一次。在调用 forEach
开始后添加的新键会被访问。如果在访问之后删除了键,并且在
forEach
调用完成之前重新添加了该键,则该键将被重新访问。在调用 forEach
开始后删除的键,在被访问之前重新添加之前,不会被访问。
24.1.3.6 Map.prototype.get ( key )
调用该方法时执行以下步骤:
1. 令 M 为 this 的值。
2. 执行 ? RequireInternalSlot (M ,
[[MapData]] )。
3. 对于 M .[[MapData]] 中的每个
Record
{ [[Key]] , [[Value]] } p ,执行以下步骤:
a. 如果 p .[[Key]] 不为
empty ,
并且执行 ? SameValueZero (p .[[Key]] , key ) 为 true ,则返回 p .[[Value]] 。
4. 返回 undefined 。
24.1.3.7 Map.prototype.has ( key )
调用该方法时执行以下步骤:
1. 令 M 为 this 的值。
2. 执行 ? RequireInternalSlot (M ,
[[MapData]] )。
3. 对于 M .[[MapData]] 中的每个
Record
{ [[Key]] , [[Value]] } p ,执行以下步骤:
a. 如果 p .[[Key]] 不为
empty ,
并且执行 ? SameValueZero (p .[[Key]] , key ) 为 true ,则返回
true 。
4. 返回 false 。
24.1.3.8 Map.prototype.keys ( )
调用该方法时执行以下步骤:
1. 令 M 为 this 的值。
2. 返回 ? CreateMapIterator (M ,
key )。
24.1.3.9 Map.prototype.set ( key , value )
调用该方法时执行以下步骤:
1. 令 M 为 this 的值。
2. 执行 ? RequireInternalSlot (M ,
[[MapData]] )。
3. 对于 M .[[MapData]] 中的每个
Record
{ [[Key]] , [[Value]] } p ,执行以下步骤:
a. 如果 p .[[Key]] 不是
empty 并且 ? SameValueZero (p .[[Key]] , key ) 是 true ,则
i. 将 p .[[Value]] 设置为
value 。
ii. 返回 M 。
4. 如果 key 是 -0 𝔽 ,则将
key 设置为 +0 𝔽 。
5. 令 p 为 Record
{ [[Key]] : key , [[Value]] :
value }。
6. 将 p 追加到 M .[[MapData]] 。
7. 返回 M 。
24.1.3.10 get Map.prototype.size
Map.prototype.size
是一个 访问器属性 ,其设置访问器函数为
undefined 。其获取访问器函数在调用时执行以下步骤:
1. 令 M 为 this 的值。
2. 执行 ? RequireInternalSlot (M ,
[[MapData]] )。
3. 令 count 为 0。
4. 对于 M .[[MapData]] 中的每个
Record
{ [[Key]] , [[Value]] } p ,执行以下步骤:
a. 如果 p .[[Key]] 不是
empty ,则将 count 设置为 count + 1。
5. 返回 𝔽 (count )。
24.1.3.11 Map.prototype.values ( )
调用该方法时执行以下步骤:
1. 令 M 为 this 的值。
2. 返回 ? CreateMapIterator (M ,
value )。
24.1.3.12 Map.prototype [ @@iterator ] ( )
@@iterator 属性的初始值为
%Map.prototype.entries%,定义在 24.1.3.4 。
24.1.3.13 Map.prototype [ @@toStringTag ]
@@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 方法创建迭代器对象。调用时执行以下步骤:
1. 执行 ? RequireInternalSlot (map ,
[[MapData]] ).
2. 让 closure 成为一个新的 抽象闭包 ,没有参数,捕获 map 和
kind ,并在调用时执行以下步骤:
a. 让 entries 为 map .[[MapData]] 。
b. 让 index 为 0。
c. 让 numEntries 为 entries 中的元素数量。
d. 重复,直到 index < numEntries ,
i. 让 e 为 entries [index ]。
ii. 将 index 设置为 index + 1。
iii. 如果 e .[[Key]] 不是
empty ,则
1. 如果 kind 是 key ,则
a. 让 result 为 e .[[Key]] 。
2. 否则,如果 kind 是
value ,则
a. 让 result 为 e .[[Value]] 。
3. 否则,
a. 断言 : kind 是
key+value 。
b. 让 result 为 CreateArrayFromList («
e .[[Key]] , e .[[Value]] »)。
4. 执行 ? GeneratorYield (CreateIterResultObject (result ,
false )).
5. 注:在执行此抽象操作时,如果 Yield
暂停了,entries 中的元素数量可能会增加。
6. 将 numEntries 设置为 entries
中的元素数量。
e. 返回 undefined 。
3. 返回 CreateIteratorFromClosure (closure ,
"%MapIteratorPrototype%" ,%MapIteratorPrototype% ).
24.1.5.2 %MapIteratorPrototype% 对象
%MapIteratorPrototype% 对象:
24.1.5.2.1 %MapIteratorPrototype%.next ( )
1. 返回 ? GeneratorResume (this
值,empty ,"%MapIteratorPrototype%" ).
24.1.5.2.2 %MapIteratorPrototype% [ @@toStringTag ]
@@toStringTag 属性的初始值为
字符串值 "Map Iterator" 。
该属性具有属性 { [[Writable]] : false ,
[[Enumerable]] : false , [[Configurable]] : true }。
24.2 Set 对象
Set 对象是 ECMAScript 语言值 的集合。一个不同的值只能在
Set 的集合中出现一次。不同的值使用 SameValueZero 比较算法来区分。
Set 对象必须使用哈希表或其他机制实现,这些机制在平均情况下提供的访问时间应该是对集合中元素数量的次线性。此规范中使用的数据结构仅用于描述 Set 对象所需的可观察语义。它不应作为可行的实现模型。
24.2.1 Set 构造函数
Set 构造函数 :
是 %Set% 。
是 "Set" 属性的初始值,属于 全局对象 。
当作为 构造函数 调用时,创建并初始化一个新的 Set 对象。
不打算作为函数调用,若以这种方式调用将抛出异常。
可以用作类定义中的 extends
子句的值。旨在继承指定 Set 行为的子类 构造函数 必须包含对 Set 构造函数
的 super
调用,以创建和初始化子类实例,并具备支持 Set.prototype
内置方法所需的内部状态。
24.2.1.1 Set ( [ iterable ] )
此函数在调用时执行以下步骤:
1. 如果 NewTarget 是 undefined ,则抛出
TypeError 异常。
2. 让 set 为 ? OrdinaryCreateFromConstructor (NewTarget,
"%Set.prototype%" , « [[SetData]] »)。
3. 将 set .[[SetData]] 设置为一个新的空的
列表 。
4. 如果 iterable 为 undefined 或
null ,则返回 set 。
5. 让 adder 为 ? Get (set , "add" )。
6. 如果 IsCallable (adder ) 为
false ,则抛出 TypeError 异常。
7. 让 iteratorRecord 为 ? GetIterator (iterable ,
sync )。
8. 重复,
a. 让 next 为 ? IteratorStepValue (iteratorRecord )。
b. 如果 next 为 done ,则返回
set 。
c. 让 status 为 Completion (Call (adder , set , «
next »))。
d. IfAbruptCloseIterator (status ,
iteratorRecord )。
24.2.2 Set 构造函数的属性
Set 构造函数 :
24.2.2.1 Set.prototype
Set.prototype
的初始值为 Set
原型对象 。
该属性的特性为 { [[Writable]] : false ,
[[Enumerable]] : false , [[Configurable]] : false }。
24.2.2.2 获取 Set [ @@species ]
Set[@@species]
是一个 访问器属性 ,其设置访问器函数为
undefined 。其获取访问器函数在调用时执行以下步骤:
1. 返回 this 值。
该函数的 "name" 属性值为 "get [Symbol.species]" 。
注
创建派生集合对象的方法应调用 @@species 来确定
用于创建派生对象的 构造函数 。子类 构造函数 可以重写 @@species 以更改默认的 构造函数 分配。
24.2.3 Set 原型对象的属性
Set 原型对象 :
24.2.3.1 Set.prototype.add ( value )
调用此方法时执行以下步骤:
1. 让 S 为 this 值。
2. 执行 ? RequireInternalSlot (S ,
[[SetData]] )。
3. 对于 S .[[SetData]] 的每个元素
e ,执行
a. 如果 e 不是 empty 且
SameValueZero (e ,
value ) 为 true ,则
i. 返回 S 。
4. 如果 value 为 -0 𝔽 ,将
value 设置为 +0 𝔽 。
5. 将 value 添加到 S .[[SetData]] 中。
6. 返回 S 。
24.2.3.2 Set.prototype.clear ( )
调用此方法时执行以下步骤:
1. 让 S 为 this 值。
2. 执行 ? RequireInternalSlot (S ,
[[SetData]] )。
3. 对于 S .[[SetData]] 的每个元素
e ,执行
a. 将 S .[[SetData]] 中值为
e 的元素替换为值为 empty 的元素。
4. 返回 undefined 。
注
现有的 [[SetData]] List
被保留,因为可能存在处于迭代中途暂停的 Set Iterator 对象,这些对象正在迭代该 List 。
24.2.3.3 Set.prototype.constructor
Set.prototype.constructor
的初始值是 %Set% 。
24.2.3.4 Set.prototype.delete ( value )
调用此方法时执行以下步骤:
1. 让 S 为 this 值。
2. 执行 ? RequireInternalSlot (S ,
[[SetData]] )。
3. 对于 S .[[SetData]] 的每个元素
e ,执行
a. 如果 e 不是 empty 且
SameValueZero (e ,
value ) 为 true ,则
i. 将 S .[[SetData]] 中值为
e 的元素替换为值为 empty 的元素。
ii. 返回 true 。
4. 返回 false 。
注
值 empty 用作规范设备,以指示某个条目已被删除。实际实现可能会采取其他措施,如从内部数据结构中物理删除条目。
24.2.3.5 Set.prototype.entries ( )
调用此方法时执行以下步骤:
1. 让 S 为 this 值。
2. 返回 ? CreateSetIterator (S ,
key+value )。
注
在迭代过程中,Set 的表现类似于 Map,其中每个条目的键和值相同。
24.2.3.6 Set.prototype.forEach ( callbackfn [ ,
thisArg ] )
调用此方法时执行以下步骤:
1. 让 S 为 this 值。
2. 执行 ? RequireInternalSlot (S ,
[[SetData]] )。
3. 如果 IsCallable (callbackfn ) 为
false ,则抛出 TypeError 异常。
4. 让 entries 为 S .[[SetData]] 。
5. 让 numEntries 为 entries 中的元素数量。
6. 让 index 为 0。
7. 重复以下步骤,直到 index < numEntries :
a. 让 e 为 entries [index ]。
b. 将 index 设为 index + 1。
c. 如果 e 不是 empty ,则:
i. 执行 ? Call (callbackfn , thisArg , «
e , e , S »)。
ii. 注意:在执行 callbackfn 期间,entries
中的元素数量可能会增加。
iii. 将 numEntries 设为 entries 中的元素数量。
8. 返回 undefined 。
注
callbackfn 应该是一个接受三个参数的函数。forEach
会对 Set 对象中每个值调用一次
callbackfn ,以值的插入顺序。callbackfn 仅对 Set 中实际存在的值进行调用;对已从 Set 中删除的键不会调用。
如果提供了 thisArg 参数,它将被用作每次调用 callbackfn 的 this 值。如果未提供,则使用
undefined 。
callbackfn 会接收三个参数:前两个参数是 Set 中的一个值。两个参数传递的是相同的值。遍历中的 Set 对象作为第三个参数传递。
callbackfn 使用三个参数是为了与 Map 和 Array 的 forEach
方法中的回调函数保持一致。对于 Sets,每个项值被认为是键和值。
forEach
不直接改变其调用的对象,但该对象可能会通过调用 callbackfn 发生变化。
每个值通常只访问一次。然而,如果一个值在被访问后被删除,然后在 forEach
调用完成前重新添加,则该值会被重新访问。在 forEach
开始后删除的值不会被访问,除非在 forEach
调用完成前再次添加。 forEach
开始后添加的新值会被访问。
24.2.3.7 Set.prototype.has ( value )
调用此方法时执行以下步骤:
1. 让 S 为 this 值。
2. 执行 ? RequireInternalSlot (S ,
[[SetData]] )。
3. 对于 S .[[SetData]] 中的每个元素
e ,执行
a. 如果 e 不是 empty 并且 SameValueZero (e ,
value ) 为 true ,则返回 true 。
4. 返回 false 。
24.2.3.8 Set.prototype.keys ( )
"keys" 属性的初始值为 %Set.prototype.values%,定义在 24.2.3.10 。
注
在迭代时,Set 看起来类似于 Map,其中每个条目的键和值相同。
24.2.3.9 get Set.prototype.size
Set.prototype.size
是一个 访问器属性 ,其设置访问器函数为
undefined 。其获取访问器函数在调用时执行以下步骤:
1. 让 S 为 this 值。
2. 执行 ? RequireInternalSlot (S ,
[[SetData]] )。
3. 让 count 为 0。
4. 对 S .[[SetData]] 的每个元素
e 执行
a. 如果 e 不是 empty ,将
count 设为 count + 1。
5. 返回 𝔽 (count )。
24.2.3.10 Set.prototype.values ( )
此方法在调用时执行以下步骤:
1. 让 S 为 this 值。
2. 返回 ? CreateSetIterator (S ,
value )。
24.2.3.11 Set.prototype [ @@iterator ] ( )
@@iterator 属性的初始值是
%Set.prototype.values%,在 24.2.3.10 中定义。
24.2.3.12 Set.prototype [ @@toStringTag ]
@@toStringTag 属性的初始值是字符串值
"Set" 。
此属性具有 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
true } 的属性特性。
24.2.4 Set 实例的属性
Set 实例是从 Set 原型继承属性的 普通对象 。Set 实例还有一个 [[SetData]] 内部槽位。
24.2.5 Set 迭代器对象
Set 迭代器是一个 普通对象 ,其结构如下所定义,表示对某个特定 Set 实例对象的特定迭代。Set
迭代器对象没有命名的 构造函数 。相反,Set 迭代器对象是通过调用 Set 实例对象的某些方法来创建的。
24.2.5.1 CreateSetIterator ( set , kind )
抽象操作 CreateSetIterator 接受参数 set (一个 ECMAScript
语言值 )和 kind (key+value 或
value ),并返回一个 正常完成
包含一个生成器或一个 抛出完成 。它用于为返回此类迭代器的
Set 方法创建迭代器对象。它在调用时执行以下步骤:
1. 执行 ? RequireInternalSlot (set ,
[[SetData]] )。
2. 让 closure 成为一个新的 抽象闭包 ,没有参数,捕获 set 和
kind ,并在调用时执行以下步骤:
a. 让 index 为 0。
b. 让 entries 为 set .[[SetData]] 。
c. 让 numEntries 为 entries 中元素的数量。
d. 重复执行,当 index < numEntries 时,
i. 让 e 为 entries [index ]。
ii. 将 index 设置为 index + 1。
iii. 如果 e 不为空,则
1. 如果 kind 为
key+value ,则
a. 让 result 为 CreateArrayFromList («
e , e »)。
b. 执行 ? GeneratorYield (CreateIterResultObject (result ,
false ))。
2. 否则,
a. 断言 :kind 为
value 。
b. 执行 ? GeneratorYield (CreateIterResultObject (e ,
false ))。
3. 注意:在执行此抽象操作时,由于 Yield
暂停,entries 中的元素数量可能已增加。
4. 将 numEntries 设置为 entries
中元素的数量。
e. 返回 undefined 。
3. 返回 CreateIteratorFromClosure (closure ,
"%SetIteratorPrototype%" ,%SetIteratorPrototype% )。
24.2.5.2 %SetIteratorPrototype% 对象
%SetIteratorPrototype% 对象:
24.2.5.2.1 %SetIteratorPrototype%.next ( )
1. 返回 ? GeneratorResume (this
值,empty ,"%SetIteratorPrototype%" )。
24.2.5.2.2 %SetIteratorPrototype% [ @@toStringTag ]
@@toStringTag 属性的初始值为字符串值
"Set Iterator" 。
该属性具有以下特性:{ [[Writable]] : false ,
[[Enumerable]] : false , [[Configurable]] :
true }。
24.3 WeakMap 对象
WeakMap 是键/值对的集合,其中键是对象和/或符号,而值可以是任意的 ECMAScript 语言值 。可以查询 WeakMap
以查看它是否包含具有特定键的键/值对,但没有机制提供枚举它作为键所持有的值。在某些条件下,不是 活动 的值会作为 WeakMap 键被移除,如 9.10.3 所述。
实现可能在 WeakMap 的键/值对变得不可访问和从 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》,第 14 卷,第 21 期,第 3481-3497 页,2008 年,http://www.jucs.org/jucs_14_21/eliminating_cycles_in_weak
24.3.1 WeakMap 构造函数
WeakMap 构造函数 :
是 %WeakMap% 。
是 全局对象 的 "WeakMap"
属性的初始值。
在作为 构造函数 调用时,会创建并初始化一个新的 WeakMap。
不打算作为函数调用,并且如果以这种方式调用将抛出异常。
可以在类定义的 extends
子句中用作值。意图继承指定 WeakMap 行为的子类 构造函数 必须包括对 WeakMap
构造函数 的 super
调用,以创建并初始化子类实例,并具有支持 WeakMap.prototype
内置方法所需的内部状态。
24.3.1.1 WeakMap ( [ iterable ] )
当调用此函数时,执行以下步骤:
1. 如果 NewTarget 是 undefined ,抛出一个
TypeError 异常。
2. 让 map 为 ? OrdinaryCreateFromConstructor (NewTarget,
"%WeakMap.prototype%" , « [[WeakMapData]] »)。
3. 将 map .[[WeakMapData]]
设置为一个新的空 列表 。
4. 如果 iterable 是 undefined 或
null ,返回 map 。
5. 让 adder 为 ? Get (map , "set" ).
6. 如果 IsCallable (adder ) 为
false ,抛出一个 TypeError 异常。
7. 返回 ? AddEntriesFromIterable (map , iterable ,
adder )。
注
如果参数 iterable 存在,它应该是一个实现了 @@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 )
此方法在调用时执行以下步骤:
1. 让 M 为 this 的值。
2. 执行 ? RequireInternalSlot (M ,
[[WeakMapData]] )。
3. 如果 CanBeHeldWeakly (key )
是 false ,返回 false 。
4. 对于 Record
{ [[Key]] , [[Value]] } p 的每个
M .[[WeakMapData]] ,执行
a. 如果 p .[[Key]] 不是
empty 且 SameValue (p .[[Key]] , key ) 是 true ,则
i. 将 p .[[Key]] 设置为
empty 。
ii. 将 p .[[Value]] 设置为
empty 。
iii. 返回 true 。
5. 返回 false 。
注
值 empty 用作规范设备以指示条目已被删除。实际实现可能采取其他措施,例如实际从内部数据结构中删除条目。
24.3.3.3 WeakMap.prototype.get ( key )
此方法在调用时执行以下步骤:
1. 让 M 为 this 的值。
2. 执行 ? RequireInternalSlot (M ,
[[WeakMapData]] )。
3. 如果 CanBeHeldWeakly (key )
是 false ,返回 undefined 。
4. 对于 Record
{ [[Key]] , [[Value]] } p 的每个
M .[[WeakMapData]] ,执行
a. 如果 p .[[Key]] 不是
empty 且 SameValue (p .[[Key]] , key ) 是 true ,返回
p .[[Value]] 。
5. 返回 undefined 。
24.3.3.4 WeakMap.prototype.has ( key )
此方法在调用时执行以下步骤:
1. 让 M 为 this 的值。
2. 执行 ? RequireInternalSlot (M ,
[[WeakMapData]] )。
3. 如果 CanBeHeldWeakly (key )
是 false ,返回 false 。
4. 对于 Record
{ [[Key]] , [[Value]] } p 的每个
M .[[WeakMapData]] ,执行
a. 如果 p .[[Key]] 不是
empty 且 SameValue (p .[[Key]] , key ) 是 true ,返回
true 。
5. 返回 false 。
24.3.3.5 WeakMap.prototype.set ( key , value )
此方法在调用时执行以下步骤:
1. 让 M 为 this 的值。
2. 执行 ? RequireInternalSlot (M ,
[[WeakMapData]] )。
3. 如果 CanBeHeldWeakly (key )
是 false ,抛出 TypeError 异常。
4. 对于 Record
{ [[Key]] , [[Value]] } p 的每个
M .[[WeakMapData]] ,执行
a. 如果 p .[[Key]] 不是
empty 且 SameValue (p .[[Key]] , key ) 是 true ,则
i. 将 p .[[Value]] 设置为
value 。
ii. 返回 M 。
5. 让 p 为 Record
{ [[Key]] : key , [[Value]] :
value }。
6. 将 p 附加到 M .[[WeakMapData]] 。
7. 返回 M 。
24.3.3.6 WeakMap.prototype [ @@toStringTag ]
@@toStringTag 属性的初始值是
字符串值 "WeakMap" 。
此属性具有 { [[Writable]] : false ,
[[Enumerable]] : false , [[Configurable]] :
true } 的特性。
24.3.4 WeakMap 实例的属性
WeakMap 实例是 普通对象 ,从 WeakMap 原型继承属性。WeakMap 实例还具有一个
[[WeakMapData]] 内部槽。
24.4 WeakSet 对象
WeakSets 是对象和/或符号的集合。一个独特的对象或符号在 WeakSet 的集合中只能出现一次。可以查询 WeakSet 以查看是否包含特定值,但没有机制提供列举其包含的值。在某些条件下,不再
存活 的值将被移除作为 WeakSet 元素,如 9.10.3 中所述。
实现可能在值变得不可访问和从 WeakSet 中移除之间施加任意确定的延迟。如果这种延迟对 ECMAScript 程序可见,它将成为影响程序执行的不确定因素。因此,ECMAScript 实现不得提供任何手段来确定
WeakSet 是否包含某个特定值,且不要求观察者提供观察到的值。
WeakSets 必须使用哈希表或其他机制来实现,这些机制在平均情况下提供比集合中元素数量更低的访问时间。本规范中使用的数据结构仅用于描述 WeakSets 的可观察语义,并不是可行的实现模型。
注
24.4.1 WeakSet 构造函数
WeakSet 构造函数 :
是 %WeakSet% 。
是 全局对象 的 "WeakSet"
属性的初始值。
当被调用为 构造函数 时,创建并初始化一个新的 WeakSet。
不打算作为函数调用,若以这种方式调用将抛出异常。
可以用作类定义的 extends
子句中的值。意图继承指定 WeakSet 行为的子类 构造函数 必须包含一个对
WeakSet 构造函数 的 super
调用,以使用支持 WeakSet.prototype
内建方法所需的内部状态来创建并初始化子类实例。
24.4.1.1 WeakSet ( [ iterable ] )
当调用此函数时,执行以下步骤:
1. 如果 NewTarget 是 undefined ,则抛出
TypeError 异常。
2. 让 set 为 ? OrdinaryCreateFromConstructor (NewTarget,
"%WeakSet.prototype%" , « [[WeakSetData]] »)。
3. 将 set .[[WeakSetData]]
设置为一个新的空的 列表 。
4. 如果 iterable 是 undefined 或
null ,则返回 set 。
5. 让 adder 为 ? Get (set , "add" )。
6. 如果 IsCallable (adder ) 为
false ,则抛出 TypeError 异常。
7. 让 iteratorRecord 为 ? GetIterator (iterable , sync )。
8. 重复,
a. 让 next 为 ? IteratorStepValue (iteratorRecord )。
b. 如果 next 是 done ,则返回
set 。
c. 让 status 为 Completion (Call (adder , set , «
next »))。
d. 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 )
此方法在调用时执行以下步骤:
1. 令 S 为 this 值。
2. 执行 ? RequireInternalSlot (S ,
[[WeakSetData]] )。
3. 如果 CanBeHeldWeakly (value )
为
false ,则抛出 TypeError 异常。
4. 对于 S .[[WeakSetData]] 中的每个元素
e ,执行
a. 如果 e 不为空且 SameValue (e ,
value ) 为
true ,则
i. 返回 S 。
5. 将 value 添加到 S .[[WeakSetData]] 中。
6. 返回 S 。
24.4.3.2 WeakSet.prototype.constructor
WeakSet.prototype.constructor
的初始值是 %WeakSet% 。
24.4.3.3 WeakSet.prototype.delete ( value )
此方法在调用时执行以下步骤:
1. 令 S 为 this 值。
2. 执行 ? RequireInternalSlot (S ,
[[WeakSetData]] )。
3. 如果 CanBeHeldWeakly (value )
为
false ,则返回 false 。
4. 对于 S .[[WeakSetData]] 中的每个元素
e ,执行
a. 如果 e 不为空且 SameValue (e ,
value ) 为
true ,则
i. 用一个值为空的元素替换 S .[[WeakSetData]] 中的
元素 e 。
ii. 返回 true 。
5. 返回 false 。
注
值 empty 用作规范设备,以指示一个条目已被删除。实际实现可能会采取其他措施,如物理移除条目。
24.4.3.4 WeakSet.prototype.has ( value )
此方法在调用时执行以下步骤:
1. 令 S 为 this 值。
2. 执行 ? RequireInternalSlot (S ,
[[WeakSetData]] )。
3. 如果 CanBeHeldWeakly (value )
为
false ,则返回 false 。
4. 对于 S .[[WeakSetData]] 中的每个元素
e ,执行
a. 如果 e 不为空且 SameValue (e ,
value ) 为
true ,则返回 true 。
5. 返回 false 。
24.4.3.5 WeakSet.prototype [ @@toStringTag ]
@@toStringTag 属性的初始值为
字符串值 "WeakSet" 。
该属性的特性为 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
true }。
24.4.4 WeakSet 实例的属性
WeakSet 实例是继承自 WeakSet 原型的 普通对象 。WeakSet 实例还具有一个 [[WeakSetData]] 内部槽。
25 结构化数据
25.1 ArrayBuffer 对象
25.1.1 表示法
本节、25.4 和 29 中的描述使用了读-修改-写修改函数内部数据结构。
一个 读-修改-写修改函数
是一个数学函数,其表示为一个抽象闭包,接受两个 列表 的
字节值 作为参数,并返回一个 列表 的
字节值 。这些抽象闭包满足以下所有属性:
它们以原子方式执行所有算法步骤。
它们的单个算法步骤不可观察。
注
为了验证读-修改-写修改函数的算法步骤构成纯数学函数,建议使用以下编辑规范:
它们不直接或通过调用的 抽象操作
和抽象闭包,访问除其参数和捕获值以外的任何语言或规范值。
它们不返回 完成记录 。
25.1.2 固定长度和可调整大小的 ArrayBuffer 对象
一个 固定长度的 ArrayBuffer 是一个在创建后其字节长度不能改变的 ArrayBuffer。
一个 可调整大小的 ArrayBuffer 是一个在创建后可以通过调用 ArrayBuffer.prototype.resize (
newLength ) 改变其字节长度的 ArrayBuffer。
创建的 ArrayBuffer 对象的类型取决于传递给 ArrayBuffer ( length [ ,
options ] ) 的参数。
25.1.3 ArrayBuffer 对象的抽象操作
25.1.3.1 AllocateArrayBuffer ( constructor ,
byteLength
[ , maxByteLength ] )
抽象操作 AllocateArrayBuffer 接受参数 constructor (一个 构造函数 )和 byteLength
(一个非负的 整数 )以及可选参数
maxByteLength (一个非负的 整数 或 empty )
并返回一个 正常完成 ,
包含一个 ArrayBuffer 或一个 异常完成 。
它用于创建一个 ArrayBuffer。调用时执行以下步骤:
1. 让 slots 为 « [[ArrayBufferData]] ,[[ArrayBufferByteLength]] ,
[[ArrayBufferDetachKey]] ».
2. 如果 maxByteLength 存在且
maxByteLength 不为 empty ,则让
allocatingResizableBuffer
为 true ;否则,让 allocatingResizableBuffer 为
false 。
3. 如果 allocatingResizableBuffer 为
true ,则
a. 如果 byteLength > maxByteLength ,
抛出一个 RangeError 异常。
b. 将 [[ArrayBufferMaxByteLength]]
添加到 slots 中。
4. 让 obj 为 ? OrdinaryCreateFromConstructor (constructor ,
"%ArrayBuffer.prototype%" ,slots )。
5. 让 block 为 ? CreateByteDataBlock (byteLength )。
6. 将 obj .[[ArrayBufferData]]
设置为 block 。
7. 将 obj .[[ArrayBufferByteLength]] 设置为 byteLength 。
8. 如果 allocatingResizableBuffer 为
true ,则
a. 如果无法创建一个大小为 maxByteLength 的 数据块 ,
抛出一个 RangeError 异常。
b. 注意:可调整大小的 ArrayBuffers 设计为可在原地增长。实现可能会抛出异常,例如如果无法预先保留虚拟内存。
c. 将 obj .[[ArrayBufferMaxByteLength]] 设置为 maxByteLength 。
9. 返回 obj 。
25.1.3.2 ArrayBufferByteLength ( arrayBuffer ,
order
)
抽象操作 ArrayBufferByteLength 接受参数 arrayBuffer (一个 ArrayBuffer 或
SharedArrayBuffer)和 order (seq-cst 或
unordered ),并返回一个非负的 整数 。调用时执行以下步骤:
1. 如果 IsSharedArrayBuffer (arrayBuffer )
为 true 且 arrayBuffer 具有 [[ArrayBufferByteLengthData]] 内部槽,则
a. 让 bufferByteLengthBlock 为
arrayBuffer .[[ArrayBufferByteLengthData]] 。
b. 让 rawLength 为 GetRawBytesFromSharedBlock (bufferByteLengthBlock ,
0, biguint64 , true , order )。
c. 让 isLittleEndian 为 [[LittleEndian]] 字段的值,来自 周围代理 的
代理记录 。
d. 返回 ℝ (RawBytesToNumeric (biguint64 ,
rawLength , isLittleEndian ))。
2. Assert : IsDetachedBuffer (arrayBuffer )
为 false 。
3. 返回 arrayBuffer .[[ArrayBufferByteLength]] 。
25.1.3.3 ArrayBufferCopyAndDetach ( arrayBuffer ,
newLength , preserveResizability )
抽象操作 ArrayBufferCopyAndDetach 接受参数 arrayBuffer (一个 ECMAScript
语言值 ),newLength (一个 ECMAScript
语言值 ),和 preserveResizability
(preserve-resizability 或 fixed-length ),并返回
一个
正常完成
包含一个 ArrayBuffer 或一个 抛出完成 。
调用时执行以下步骤:
1. 执行 ? RequireInternalSlot (arrayBuffer ,
[[ArrayBufferData]] )。
2. 如果 IsSharedArrayBuffer (arrayBuffer )
为 true ,则抛出一个 TypeError 异常。
3. 如果 newLength 为 undefined ,则
a. 让 newByteLength 为
arrayBuffer .[[ArrayBufferByteLength]] 。
4. 否则,
a. 让 newByteLength 为 ? ToIndex (newLength )。
5. 如果 IsDetachedBuffer (arrayBuffer )
为 true ,则抛出一个 TypeError 异常。
6. 如果 preserveResizability 为
preserve-resizability 且 IsFixedLengthArrayBuffer (arrayBuffer )
为 false ,则
a. 让 newMaxByteLength 为
arrayBuffer .[[ArrayBufferMaxByteLength]] 。
7. 否则,
a. 让 newMaxByteLength 为
empty 。
8. 如果 arrayBuffer .[[ArrayBufferDetachKey]] 不为 undefined ,则抛出一个
TypeError 异常。
9. 让 newBuffer 为 ? AllocateArrayBuffer (%ArrayBuffer% ,
newByteLength , newMaxByteLength )。
10. 让 copyLength 为 min (newByteLength ,
arrayBuffer .[[ArrayBufferByteLength]] )。
11. 让 fromBlock 为 arrayBuffer .[[ArrayBufferData]] 。
12. 让 toBlock 为 newBuffer .[[ArrayBufferData]] 。
13. 执行 CopyDataBlockBytes (toBlock ,
0, fromBlock , 0, copyLength )。
14. 注:新 数据块
的创建或从旧的 数据块 的复制
都不可观察。
实现可能将此方法实现为零复制移动或 realloc
。
15. 执行 ! DetachArrayBuffer (arrayBuffer )。
16. 返回 newBuffer 。
25.1.3.4 IsDetachedBuffer ( arrayBuffer )
抽象操作 IsDetachedBuffer 接受参数 arrayBuffer (一个 ArrayBuffer 或 SharedArrayBuffer),并返回一个布尔值。调用时执行以下步骤:
1. 如果 arrayBuffer .[[ArrayBufferData]] 为 null ,则返回
true 。
2. 返回 false 。
25.1.3.5 DetachArrayBuffer ( arrayBuffer [ , key ]
)
抽象操作 DetachArrayBuffer 接受参数 arrayBuffer (一个 ArrayBuffer)和可选参数 key (任意值),并返回一个
正常完成
包含 unused 或一个 抛出完成 。
调用时执行以下步骤:
1. 断言 : IsSharedArrayBuffer (arrayBuffer )
为 false 。
2. 如果 key 不存在,则将 key 设置为
undefined 。
3. 如果 arrayBuffer .[[ArrayBufferDetachKey]] 不等于 key ,则抛出一个
TypeError 异常。
4. 将 arrayBuffer .[[ArrayBufferData]] 设置为 null 。
5. 将 arrayBuffer .[[ArrayBufferByteLength]] 设置为 0。
6. 返回 unused 。
注
分离一个 ArrayBuffer 实例会将用作其后备存储的 数据块
与实例断开关联,并将缓冲区的字节长度设置为 0。
25.1.3.6 CloneArrayBuffer ( srcBuffer ,
srcByteOffset ,
srcLength )
抽象操作 CloneArrayBuffer 接受参数 srcBuffer (一个 ArrayBuffer 或
SharedArrayBuffer),srcByteOffset (一个非负 整数 ),以及 srcLength (一个
非负 整数 ),
并返回一个 正常完成
包含 的 ArrayBuffer 或一个 抛出完成 。
它创建一个新的 ArrayBuffer,其数据是 srcBuffer 数据的拷贝,拷贝范围从 srcByteOffset 开始,长度为
srcLength
字节。
调用时执行以下步骤:
1. 断言 : IsDetachedBuffer (srcBuffer )
为 false 。
2. 让 targetBuffer 为 ? AllocateArrayBuffer (%ArrayBuffer% ,
srcLength )。
3. 让 srcBlock 为 srcBuffer .[[ArrayBufferData]] 。
4. 让 targetBlock 为 targetBuffer .[[ArrayBufferData]] 。
5. 执行 CopyDataBlockBytes (targetBlock ,
0, srcBlock , srcByteOffset , srcLength ).
6. 返回 targetBuffer 。
25.1.3.7 GetArrayBufferMaxByteLengthOption ( options )
抽象操作 GetArrayBufferMaxByteLengthOption 接受参数 options (一个
ECMAScript 语言值 ),并返回一个
正常完成
包含 一个非负的 整数 或
empty ,或者一个 抛出完成 。
调用时执行以下步骤:
1. 如果 options 不是一个对象 ,返回
empty 。
2. 让 maxByteLength 为 ? Get (options ,
"maxByteLength" ).
3. 如果 maxByteLength 为 undefined ,
返回 empty 。
4. 返回 ? 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)并返回一个布尔值。调用时执行以下步骤:
1. 如果 arrayBuffer 具有一个 [[ArrayBufferMaxByteLength]] 内部槽,则返回 false 。
2. 返回 true 。
25.1.3.10 IsUnsignedElementType ( type )
抽象操作 IsUnsignedElementType 接受参数 type (一个 TypedArray
元素类型 )
并返回一个布尔值。它验证参数 type 是否是一个无符号的 TypedArray 元素类型 。调用时执行以下步骤:
1. 如果 type 是
uint8 、uint8clamped 、uint16 、uint32
或 biguint64 之一,则返回 true 。
2. 返回 false 。
25.1.3.11 IsUnclampedIntegerElementType ( type )
抽象操作 IsUnclampedIntegerElementType 接受参数 type (一个 TypedArray
元素类型 )
并返回一个布尔值。它验证参数 type 是否是一个不包括 uint8clamped 的 整数 TypedArray 元素类型 。调用时执行以下步骤:
1. 如果 type 是
int8 、uint8 、int16 、uint16 、int32
或 uint32 之一,则返回 true 。
2. 返回 false 。
25.1.3.12 IsBigIntElementType ( type )
抽象操作 IsBigIntElementType 接受参数 type (一个 TypedArray
元素类型 )
并返回一个布尔值。它验证参数 type 是否是一个 BigInt
TypedArray 元素类型 。调用时执行以下步骤:
1. 如果 type 是 biguint64 或
bigint64 之一,则返回 true 。
2. 返回 false 。
25.1.3.13 IsNoTearConfiguration ( type , order )
抽象操作 IsNoTearConfiguration 接受参数 type (一个 TypedArray
元素类型 )
和 order (seq-cst 、unordered 或
init ),并返回一个布尔值。调用时执行以下步骤:
1. 如果 IsUnclampedIntegerElementType (type )
为 true ,则返回 true 。
2. 如果 IsBigIntElementType (type )
为 true 并且 order 既不是 init 也不是
unordered ,则返回 true 。
3. 返回 false 。
25.1.3.14 RawBytesToNumeric ( type , rawBytes ,
isLittleEndian )
抽象操作 RawBytesToNumeric 接受参数 type (一个 TypedArray
元素类型 ),
rawBytes (一个 列表 的
字节
值 )和 isLittleEndian (一个布尔值),并返回一个 Number 或
BigInt。调用时执行以下步骤:
1. 让 elementSize 为 表 71 中为
元素类型 type 指定的元素大小值。
2. 如果 isLittleEndian 为 false ,则
反转 rawBytes 元素的顺序。
3. 如果 type 为 float32 ,则
a. 让 value 为 rawBytes 的字节元素
连接并解释为 little-endian 位串编码的 IEEE 754-2019 binary32
值。
b. 如果 value 为 IEEE
754-2019 binary32 NaN 值,则返回 NaN Number
值。
c. 返回与 value 对应的 Number 值。
4. 如果 type 为 float64 ,则
a. 让 value 为 rawBytes 的字节元素
连接并解释为 little-endian 位串编码的 IEEE 754-2019 binary64
值。
b. 如果 value 为 IEEE
754-2019 binary64 NaN 值,则返回 NaN Number
值。
c. 返回与 value 对应的 Number 值。
5. 如果 IsUnsignedElementType (type )
为 true ,则
a. 让 intValue 为 rawBytes 的字节元素
连接并解释为一个无符号 little-endian 二进制数字。
6. 否则,
a. 让 intValue 为 rawBytes 的字节元素
连接并解释为一个二进制 little-endian 二补数值,位长为 elementSize × 8。
7. 如果 IsBigIntElementType (type )
为 true ,返回与 intValue 对应的 BigInt 值。
8. 否则,返回与 intValue 对应的 Number 值。
25.1.3.15 GetRawBytesFromSharedBlock ( block ,
byteIndex , type , isTypedArray , order )
抽象操作 GetRawBytesFromSharedBlock 接受参数 block (一个 共享数据块 ),
byteIndex (一个非负 整数 ),type (一个 TypedArray 元素类型 ),
isTypedArray (一个布尔值),以及 order (seq-cst 或
unordered ),并返回一个 列表 的
字节值 。调用时执行以下步骤:
1. 让 elementSize 为 表 71 中为
元素类型 type 指定的元素大小值。
2. 让 execution 为 [[CandidateExecution]] 字段的 周围代理 的
代理记录 。
3. 让 eventsRecord 为 代理事件记录 的
execution .[[EventsRecords]] ,其 [[AgentSignifier]] 为
AgentSignifier ()。
4. 如果 isTypedArray 为 true 且
IsNoTearConfiguration (type ,
order ) 为 true ,则让 noTear 为 true ;
否则让 noTear 为 false 。
5. 让 rawValue 为一个长度为 elementSize 的 列表 ,其元素是非确定性选择的
字节值 。
6. 注:在实现中,rawValue 是对底层硬件的非原子或原子读取指令的结果。非确定性是 内存模型 的语义规定,用于描述具有弱一致性的硬件的可观察行为。
7. 让 readEvent 为 ReadSharedMemory
{ [[Order]] : order , [[NoTear]] :
noTear , [[Block]] : block , [[ByteIndex]] : byteIndex , [[ElementSize]] :
elementSize }.
8. 将 readEvent 添加到 eventsRecord .[[EventList]] 中。
9. 将 Chosen Value
Record { [[Event]] : readEvent , [[ChosenValue]] : rawValue } 添加到 execution .[[ChosenValues]] 中。
10. 返回 rawValue 。
25.1.3.16 GetValueFromBuffer ( arrayBuffer ,
byteIndex ,
type , isTypedArray , order [ , isLittleEndian ] )
抽象操作 GetValueFromBuffer 接受参数 arrayBuffer (一个 ArrayBuffer 或
SharedArrayBuffer),byteIndex (一个非负 整数 ),type (一个 TypedArray 元素类型 ),
isTypedArray (一个布尔值),以及 order (seq-cst 或
unordered ),以及可选参数 isLittleEndian (一个布尔值),并返回
一个数字或一个 BigInt。调用时执行以下步骤:
1. 断言 : IsDetachedBuffer (arrayBuffer )
为 false 。
2. 断言 : arrayBuffer 中从
byteIndex
开始有足够的字节来表示 type 的值。
3. 让 block 为 arrayBuffer .[[ArrayBufferData]] 。
4. 让 elementSize 为 表 71 中为
元素类型 type 指定的元素大小值。
5. 如果 IsSharedArrayBuffer (arrayBuffer )
为 true ,则
a. 断言 : block 是一个
共享数据块 。
b. 让 rawValue 为 GetRawBytesFromSharedBlock (block ,
byteIndex , type , isTypedArray , order ).
6. 否则,
a. 让 rawValue 为一个 列表
,其元素是从 block 中的字节,位于从 区间 中的索引,
从 byteIndex (含)到 byteIndex + elementSize (不含)。
7. 断言 : rawValue 的元素数量为
elementSize 。
8. 如果 isLittleEndian 不存在,将 isLittleEndian
设置为 surrounding agent 的 周围代理 的
代理记录 的 [[LittleEndian]] 字段的值。
9. 返回 RawBytesToNumeric (type ,
rawValue , isLittleEndian ).
25.1.3.17 NumericToRawBytes ( type , value ,
isLittleEndian )
抽象操作 NumericToRawBytes 接受参数 type (一个 TypedArray
元素类型 ),
value (一个数字或 BigInt),以及 isLittleEndian (一个布尔值),并返回一个
列表 ,
其元素为 字节值 。调用时执行以下步骤:
1. 如果 type 是 float32 ,则
a. 让 rawBytes 为一个 列表
,其元素为将 value 转换为 IEEE 754-2019 binary32
格式的结果。字节按小端序排列。如果 value 为 NaN ,rawBytes 可以设置为任何实现选择的
IEEE 754-2019 binary32 格式的
NaN 编码。实现必须始终为每个实现可区分的 NaN 值选择相同的编码。
2. 否则,如果 type 是 float64 ,
则
a. 让 rawBytes 为一个 列表
,其元素为将 value 转换为 IEEE
754-2019 binary64 格式的结果。字节按小端序排列。如果 value 为
NaN ,rawBytes 可以设置为任何实现选择的
IEEE 754-2019 binary64 格式的
NaN 编码。实现必须始终为每个实现可区分的 NaN 值选择相同的编码。
3. 否则,
a. 让 n 为 表 71
中为元素类型 type 指定的元素大小值。
b. 让 convOp 为在 表 71 中
为元素类型 type 指定的转换操作。
c. 让 intValue 为 ℝ (convOp (value )).
d. 如果 intValue ≥ 0,则
i. 让 rawBytes 为一个 列表
,其元素为 intValue 的 n 字节二进制编码。字节按小端序排列。
e. 否则,
i. 让 rawBytes 为一个 列表
,其元素为 intValue 的 n 字节二进制补码编码。字节按小端序排列。
4. 如果 isLittleEndian 为 false ,则
反转 rawBytes 的元素顺序。
5. 返回 rawBytes 。
25.1.3.18 SetValueInBuffer ( arrayBuffer ,
byteIndex ,
type , value , isTypedArray , order [ ,
isLittleEndian
] )
抽象操作 SetValueInBuffer 接受参数 arrayBuffer (一个 ArrayBuffer 或 SharedArrayBuffer),
byteIndex (一个非负的 整数 ),type (一个 TypedArray 元素类型 ),
value (一个数字或 BigInt),isTypedArray (一个布尔值),以及 order
(seq-cst 、unordered 或 init )和可选参数
isLittleEndian (一个布尔值),并返回 unused 。调用时执行以下步骤:
1. 断言 : IsDetachedBuffer (arrayBuffer )
为 false 。
2. 断言 : arrayBuffer 从
byteIndex
开始有足够的字节来表示 type 的值。
3. 断言 : 如果 IsBigIntElementType (type )
为 true ,则 value 是 BigInt ;否则,value
是 数字 。
4. 让 block 为 arrayBuffer .[[ArrayBufferData]] 。
5. 让 elementSize 为 表 71 中为元素类型
type 指定的元素大小值。
6. 如果 isLittleEndian 不存在,则将 isLittleEndian 设置为
[[LittleEndian]] 字段的值,该字段属于 surrounding
agent 的 Agent Record 。
7. 让 rawBytes 为 NumericToRawBytes (type ,
value , isLittleEndian ).
8. 如果 IsSharedArrayBuffer (arrayBuffer )
为 true ,则
a. 让 execution 为 [[CandidateExecution]] 字段的值,该字段属于 surrounding
agent 的 Agent Record 。
b. 让 eventsRecord 为 Agent Events
Record 的 execution .[[EventsRecords]]
,其 [[AgentSignifier]] 为 AgentSignifier ()。
c. 如果 isTypedArray 为 true 且
IsNoTearConfiguration (type ,
order ) 为 true ,则让 noTear 为
true ;否则,让 noTear 为 false 。
d. 将 WriteSharedMemory
{ [[Order]] : order , [[NoTear]] :
noTear , [[Block]] : block , [[ByteIndex]] : byteIndex ,
[[ElementSize]] : elementSize , [[Payload]] : rawBytes } 添加到 eventsRecord .[[EventList]] 。
9. 否则,
a. 将 rawBytes 的单个字节存储到 block 中,
从 block [byteIndex ] 开始。
10. 返回 unused 。
25.1.3.19 GetModifySetValueInBuffer ( arrayBuffer ,
byteIndex , type , value , op )
抽象操作 GetModifySetValueInBuffer 接受参数 arrayBuffer (一个 ArrayBuffer 或 SharedArrayBuffer),
byteIndex (一个非负的 整数 ),type (一个 TypedArray 元素类型 ),
value (一个数字或 BigInt),和 op (一个 读-修改-写修改函数 ),并返回一个数字或
BigInt。调用时执行以下步骤:
1. 断言 : IsDetachedBuffer (arrayBuffer )
为 false 。
2. 断言 : arrayBuffer 从
byteIndex
开始有足够的字节来表示 type 的值。
3. 断言 : 如果 IsBigIntElementType (type )
为 true ,则 value 是 BigInt ;否则,value
是 数字 。
4. 让 block 为 arrayBuffer .[[ArrayBufferData]] 。
5. 让 elementSize 为 表 71 中为元素类型
type 指定的元素大小值。
6. 让 isLittleEndian 为 [[LittleEndian]] 字段的值,该字段属于 surrounding
agent 的 Agent Record 。
7. 让 rawBytes 为 NumericToRawBytes (type ,
value , isLittleEndian ).
8. 如果 IsSharedArrayBuffer (arrayBuffer )
为 true ,则
a. 让 execution 为 [[CandidateExecution]] 字段的值,该字段属于 surrounding
agent 的 Agent Record 。
b. 让 eventsRecord 为 Agent Events
Record 的 execution .[[EventsRecords]]
,其 [[AgentSignifier]] 为 AgentSignifier ()。
c. 让 rawBytesRead 为一个 列表
,长度为 elementSize ,其元素是非确定性选择的 字节值 。
d. 注意: 在实现中,rawBytesRead 是对底层硬件上进行
load-link、load-exclusive 或读-修改-写指令的操作数的结果。非确定性是 内存模型
的语义规定,描述具有弱一致性的硬件的可观察行为。
e. 让 rmwEvent 为 ReadModifyWriteSharedMemory
{ [[Order]] :
seq-cst , [[NoTear]] : true , [[Block]] :
block , [[ByteIndex]] : byteIndex , [[ElementSize]] : elementSize , [[Payload]] : rawBytes , [[ModifyOp]] :
op }.
f. 将 rmwEvent 添加到
eventsRecord .[[EventList]] 。
g. 将 Chosen Value
Record { [[Event]] : rmwEvent , [[ChosenValue]] : rawBytesRead } 添加到
execution .[[ChosenValues]] 。
9. 否则,
a. 让 rawBytesRead 为一个 列表
,长度为 elementSize ,其元素是从 block [byteIndex ] 开始的
elementSize 个字节的序列。
b. 让 rawBytesModified 为
op (rawBytesRead , rawBytes )。
c. 将 rawBytesModified 的单个字节存储到 block 中,
从 block [byteIndex ] 开始。
10. 返回 RawBytesToNumeric (type ,
rawBytesRead , isLittleEndian ).
25.1.4 ArrayBuffer 构造函数
ArrayBuffer 构造函数 :
是 %ArrayBuffer% 。
是 "ArrayBuffer" 属性的初始值,该属性属于 全局对象 。
作为 构造函数 调用时,创建并初始化一个新的 ArrayBuffer。
不应作为函数调用,若以此方式调用,将抛出异常。
可以用作类定义的 extends
子句的值。旨在继承指定 ArrayBuffer 行为的子类 构造函数 必须包含对 ArrayBuffer
构造函数 的 super
调用,以创建和初始化子类实例,具备支持 ArrayBuffer.prototype
内置方法的内部状态。
25.1.4.1 ArrayBuffer ( length [ , options ] )
调用此函数时,执行以下步骤:
1. 如果 NewTarget 是 undefined ,则抛出一个
TypeError 异常。
2. 让 byteLength 为 ? ToIndex (length )。
3. 让 requestedMaxByteLength 为 ? GetArrayBufferMaxByteLengthOption (options )。
4. 返回 ? AllocateArrayBuffer (NewTarget, byteLength ,
requestedMaxByteLength )。
25.1.5 ArrayBuffer 构造函数的属性
ArrayBuffer 构造函数 :
25.1.5.1 ArrayBuffer.isView ( arg )
此函数在调用时执行以下步骤:
1. 如果 arg 不是一个对象 ,则返回
false 。
2. 如果 arg 具有一个 [[ViewedArrayBuffer]] 内部槽,则返回 true 。
3. 返回 false 。
25.1.5.2 ArrayBuffer.prototype
ArrayBuffer.prototype
的初始值是 ArrayBuffer
原型对象 。
该属性具有以下特性 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
false }。
25.1.5.3 get ArrayBuffer [ @@species ]
ArrayBuffer[@@species]
是一个 访问器属性 ,其设置访问器函数为
undefined 。其获取访问器函数在调用时执行以下步骤:
1. 返回 this 值。
此函数的 "name" 属性值为 "get [Symbol.species]" 。
注
25.1.6 ArrayBuffer 原型对象的属性
ArrayBuffer 原型对象 :
是 %ArrayBuffer.prototype% 。
具有一个 [[Prototype]] 内部槽,其值为 %Object.prototype% 。
是一个 普通对象 。
没有 [[ArrayBufferData]] 或 [[ArrayBufferByteLength]]
内部槽。
25.1.6.1 获取 ArrayBuffer.prototype.byteLength
ArrayBuffer.prototype.byteLength
是一个 访问器属性 ,其设置访问器函数是
undefined 。其获取访问器函数在调用时执行以下步骤:
1. 令 O 为 this 值。
2. 执行 ? RequireInternalSlot (O ,
[[ArrayBufferData]] )。
3. 如果 IsSharedArrayBuffer (O )
为 true ,则抛出 TypeError 异常。
4. 如果 IsDetachedBuffer (O )
为 true ,则返回 +0 𝔽 。
5. 令 length 为 O .[[ArrayBufferByteLength]] 。
6. 返回 𝔽 (length )。
25.1.6.2 ArrayBuffer.prototype.constructor
ArrayBuffer.prototype.constructor
的初始值是 %ArrayBuffer% 。
25.1.6.3 获取 ArrayBuffer.prototype.detached
ArrayBuffer.prototype.detached
是一个 访问器属性 ,其设置访问器函数是
undefined 。其获取访问器函数在调用时执行以下步骤:
1. 令 O 为 this 值。
2. 执行 ? RequireInternalSlot (O ,
[[ArrayBufferData]] )。
3. 如果 IsSharedArrayBuffer (O )
为 true ,则抛出 TypeError 异常。
4. 返回 IsDetachedBuffer (O )。
25.1.6.4 获取 ArrayBuffer.prototype.maxByteLength
ArrayBuffer.prototype.maxByteLength
是一个 访问器属性 ,其设置访问器函数是
undefined 。其获取访问器函数在调用时执行以下步骤:
1. 令 O 为 this 值。
2. 执行 ? RequireInternalSlot (O ,
[[ArrayBufferData]] )。
3. 如果 IsSharedArrayBuffer (O )
为 true ,则抛出 TypeError 异常。
4. 如果 IsDetachedBuffer (O )
为 true ,则返回 +0 𝔽 。
5. 如果 IsFixedLengthArrayBuffer (O )
为 true ,则
a. 令 length 为 O .[[ArrayBufferByteLength]] 。
6. 否则,
a. 令 length 为 O .[[ArrayBufferMaxByteLength]] 。
7. 返回 𝔽 (length )。
25.1.6.5 获取 ArrayBuffer.prototype.resizable
ArrayBuffer.prototype.resizable
是一个 访问器属性 ,其设置访问器函数是
undefined 。其获取访问器函数在调用时执行以下步骤:
1. 令 O 为 this 值。
2. 执行 ? RequireInternalSlot (O ,
[[ArrayBufferData]] )。
3. 如果 IsSharedArrayBuffer (O )
为 true ,则抛出 TypeError 异常。
4. 如果 IsFixedLengthArrayBuffer (O )
为 false ,则返回 true ;否则返回 false 。
25.1.6.6 ArrayBuffer.prototype.resize ( newLength )
该方法在调用时执行以下步骤:
1. 令 O 为 this 值。
2. 执行 ? RequireInternalSlot (O ,
[[ArrayBufferMaxByteLength]] )。
3. 如果 IsSharedArrayBuffer (O )
为 true ,则抛出 TypeError 异常。
4. 令 newByteLength 为 ? ToIndex (newLength )。
5. 如果 IsDetachedBuffer (O )
为 true ,则抛出 TypeError 异常。
6. 如果 newByteLength > O .[[ArrayBufferMaxByteLength]] ,则抛出 RangeError 异常。
7. 令 hostHandled 为 ? HostResizeArrayBuffer (O ,
newByteLength )。
8. 如果 hostHandled 为 handled ,则返回
undefined 。
9. 令 oldBlock 为 O .[[ArrayBufferData]] 。
10. 令 newBlock 为 ? CreateByteDataBlock (newByteLength )。
11. 令 copyLength 为 min (newByteLength ,
O .[[ArrayBufferByteLength]] )。
12. 执行 CopyDataBlockBytes (newBlock ,
0, oldBlock , 0, copyLength )。
13. 注意:新创建的 数据块 和从旧的 数据块
复制的过程是不可观察的。实现可以将此方法实现为就地增长或缩小。
14. 将 O .[[ArrayBufferData]] 设置为
newBlock 。
15. 将 O .[[ArrayBufferByteLength]] 设置为 newByteLength 。
16. 返回 undefined 。
25.1.6.7 ArrayBuffer.prototype.slice ( start , end )
该方法在调用时执行以下步骤:
1. 令 O 为 this 值。
2. 执行 ? RequireInternalSlot (O ,
[[ArrayBufferData]] )。
3. 如果 IsSharedArrayBuffer (O )
为 true ,则抛出 TypeError 异常。
4. 如果 IsDetachedBuffer (O )
为 true ,则抛出 TypeError 异常。
5. 令 len 为 O .[[ArrayBufferByteLength]] 。
6. 令 relativeStart 为 ? ToIntegerOrInfinity (start )。
7. 如果 relativeStart = -∞,则令 first 为 0。
8. 否则如果 relativeStart < 0,则令 first 为
max (len +
relativeStart , 0)。
9. 否则,令 first 为 min (relativeStart ,
len )。
10. 如果 end 为 undefined ,则令
relativeEnd 为 len ;否则,令 relativeEnd 为 ? ToIntegerOrInfinity (end )。
11. 如果 relativeEnd = -∞,则令 final 为 0。
12. 否则如果 relativeEnd < 0,则令 final 为
max (len +
relativeEnd , 0)。
13. 否则,令 final 为 min (relativeEnd ,
len )。
14. 令 newLen 为 max (final - first ,
0)。
15. 令 ctor 为 ? SpeciesConstructor (O , %ArrayBuffer% )。
16. 令 new 为 ? Construct (ctor , « 𝔽 (newLen ) »)。
17. 执行 ? RequireInternalSlot (new ,
[[ArrayBufferData]] )。
18. 如果 IsSharedArrayBuffer (new )
为 true ,则抛出 TypeError 异常。
19. 如果 IsDetachedBuffer (new )
为 true ,则抛出 TypeError 异常。
20. 如果 SameValue (new ,
O ) 为 true ,则抛出 TypeError 异常。
21. 如果 new .[[ArrayBufferByteLength]] < newLen ,则抛出
TypeError 异常。
22. 注意:上述步骤的副作用可能已经使 O 被分离或调整大小。
23. 如果 IsDetachedBuffer (O )
为 true ,则抛出 TypeError 异常。
24. 令 fromBuf 为 O .[[ArrayBufferData]] 。
25. 令 toBuf 为 new .[[ArrayBufferData]] 。
26. 令 currentLen 为 O .[[ArrayBufferByteLength]] 。
27. 如果 first < currentLen ,则
a. 令 count 为 min (newLen ,
currentLen - first )。
b. 执行 CopyDataBlockBytes (toBuf ,
0, fromBuf , first , count )。
28. 返回 new 。
25.1.6.8 ArrayBuffer.prototype.transfer ( [ newLength ] )
该方法在调用时执行以下步骤:
1. 令 O 为 this 值。
2. 返回 ? ArrayBufferCopyAndDetach (O , newLength ,
preserve-resizability )。
25.1.6.9 ArrayBuffer.prototype.transferToFixedLength ( [
newLength ] )
该方法在调用时执行以下步骤:
1. 令 O 为 this 值。
2. 返回 ? ArrayBufferCopyAndDetach (O , newLength ,
fixed-length )。
25.1.6.10 ArrayBuffer.prototype [ @@toStringTag ]
@@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 调用进行处理,否则会导致
TypeError 异常。此内部槽仅由某些嵌入环境设置,而非本规范中的算法。
25.1.8 可调整大小的 ArrayBuffer 指南
注 1
以下是针对 ECMAScript 程序员在使用 可调整大小的
ArrayBuffer 的指南。
我们建议在可能的情况下,在部署环境中对程序进行测试。不同硬件设备之间可用的物理内存差异很大。同样,虚拟内存子系统在硬件设备以及操作系统之间也有很大差异。一个在 64
位桌面浏览器上运行而没有内存不足错误的应用程序,在 32 位移动浏览器上可能会耗尽内存。
在为 可调整大小的
ArrayBuffer 选择 "maxByteLength" 选项的值时,我们建议选择应用程序所需的最小大小。我们建议
"maxByteLength" 不超过 1,073,741,824(2** 30
字节或 1GiB)。
请注意,成功构造一个具有特定最大大小的 可调整大小的
ArrayBuffer 并不能保证未来的调整大小操作会成功。
注 2
以下是针对 ECMAScript 实现者在实现 可调整大小的
ArrayBuffer 的指南。
可调整大小的
ArrayBuffer 可以通过在调整大小时复制、通过预先保留虚拟内存进行原地增长,或者对不同的 构造函数 的
"maxByteLength" 选项的不同值采用这两者的组合进行实现。
如果一个 宿主
是多租户的(即,它同时运行多个 ECMAScript 应用程序),例如 web 浏览器,并且其实现选择通过预留虚拟内存进行原地增长,我们建议 32 位和 64 位实现对于
"maxByteLength" ≥ 1GiB 到 1.5GiB 的值都抛出异常。这是为了降低单个应用程序耗尽虚拟内存地址空间的可能性,并减少互操作性风险。
如果一个 宿主
没有虚拟内存,例如那些运行在没有 MMU 的嵌入式设备上的宿主,或者如果一个 宿主 仅通过复制实现调整大小,则可以接受任何 Number
值 作为 "maxByteLength" 选项的值。然而,我们建议在无法分配所请求大小的内存块时抛出
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 (一个 constructor )和
byteLength
(一个非负的 整数 ),以及可选参数 maxByteLength
(一个非负的 整数 或 空 ),
并返回一个 正常完成 ,
其中包含一个 SharedArrayBuffer,或者一个 抛出完成 。
它用于创建一个 SharedArrayBuffer。当调用时执行以下步骤:
1. 设 slots 为 « [[ArrayBufferData]] »。
2. 如果 maxByteLength 存在且 maxByteLength 不是
空 ,则设 allocatingGrowableBuffer 为 true ;
否则设 allocatingGrowableBuffer 为 false 。
3. 如果 allocatingGrowableBuffer 为 true ,
则
a. 如果 byteLength > maxByteLength ,抛出
一个 RangeError 异常。
b. 将 [[ArrayBufferByteLengthData]] 和
[[ArrayBufferMaxByteLength]] 添加到 slots 。
4. 否则,
a. 将 [[ArrayBufferByteLength]] 添加到
slots 。
5. 设 obj 为 ? OrdinaryCreateFromConstructor (constructor ,
"%SharedArrayBuffer.prototype%" ,slots )。
6. 如果 allocatingGrowableBuffer 为 true ,
设 allocLength 为 maxByteLength ;否则设 allocLength 为
byteLength 。
7. 设 block 为 ? CreateSharedByteDataBlock (allocLength )。
8. 将 obj .[[ArrayBufferData]] 设为
block 。
9. 如果 allocatingGrowableBuffer 为
true ,则
a. Assert :byteLength ≤
maxByteLength 。
b. 设 byteLengthBlock 为 ? CreateSharedByteDataBlock (8)。
c. 执行 SetValueInBuffer (byteLengthBlock ,
0,biguint64 ,ℤ (byteLength ),true ,seq-cst )。
d. 将 obj .[[ArrayBufferByteLengthData]] 设为 byteLengthBlock 。
e. 将 obj .[[ArrayBufferMaxByteLength]] 设为 maxByteLength 。
10. 否则,
a. 将 obj .[[ArrayBufferByteLength]] 设为 byteLength 。
11. 返回 obj 。
25.2.2.2 IsSharedArrayBuffer( obj )
抽象操作 IsSharedArrayBuffer 接受参数 obj (一个 ArrayBuffer 或 SharedArrayBuffer),并返回一个布尔值。它测试一个对象是否是
ArrayBuffer、SharedArrayBuffer 或它们的子类型。当调用时执行以下步骤:
1. 设 bufferData 为 ? GetInternalSlot (obj ,
"[[ArrayBufferData]]" )。
2. 如果 bufferData 不为 空 ,则返回
true ;否则,返回 false 。
25.2.2.3 SharedArrayBuffer.prototype
共享数组缓冲区的原型对象:
1. SharedArrayBuffer.prototype 的值是
Object.prototype 的一个实例,且
Writable ,Enumerable 和
Configurable 属性。
2. SharedArrayBuffer.prototype 具有一个
constructor 属性,值是 SharedArrayBuffer。
3. SharedArrayBuffer.prototype 具有 toStringTag
属性,其值为 "SharedArrayBuffer" 。
25.2.3 SharedArrayBuffer 构造函数
SharedArrayBuffer 构造函数 :
是 %SharedArrayBuffer% 。
是 global 对象 的
"SharedArrayBuffer" 属性的初始值(如果该属性存在,见下文)。
当作为 构造函数 调用时,创建并初始化一个新的 SharedArrayBuffer。
不打算作为函数调用,并且在这种情况下会抛出异常。
可以作为类定义的 extends
子句的值。意图继承 SharedArrayBuffer 行为的子类 构造函数 必须包括对
SharedArrayBuffer 构造函数 的 super
调用,以创建和初始化子类实例,并具有支持 SharedArrayBuffer.prototype
内置方法所需的内部状态。
每当一个 宿主 不提供对
SharedArrayBuffers 的并发访问时,它可以省略 global 对象 的
"SharedArrayBuffer" 属性。
注
与 ArrayBuffer
不同,SharedArrayBuffer
不能变为脱离状态,其内部 [[ArrayBufferData]] 插槽从不会是 null 。
25.2.3.1 SharedArrayBuffer( length [ , options ] )
当调用此函数时,它执行以下步骤:
1. 如果 NewTarget 是 undefined ,抛出一个
TypeError 异常。
2. 设 byteLength 为 ? ToIndex (length )。
3. 设 requestedMaxByteLength 为 ? GetArrayBufferMaxByteLengthOption (options )。
4. 返回 ? AllocateSharedArrayBuffer (NewTarget,byteLength ,requestedMaxByteLength )。
25.2.4 SharedArrayBuffer 构造函数的属性
SharedArrayBuffer 构造函数 :
25.2.4.1 SharedArrayBuffer.prototype
SharedArrayBuffer.prototype
的初始值是 SharedArrayBuffer
原型对象 。
此属性具有以下属性:{ [[Writable]] : false ,
[[Enumerable]] : false , [[Configurable]] :
false }。
25.2.4.2 get SharedArrayBuffer [ @@species ]
SharedArrayBuffer[@@species]
是一个 访问器属性 ,其设置访问器函数为
undefined 。其获取访问器函数在调用时执行以下步骤:
1. 返回 this 值。
此函数的 "name" 属性值为 "get [Symbol.species]" 。
25.2.5 SharedArrayBuffer 原型对象的属性
SharedArrayBuffer 原型对象 :
是 %SharedArrayBuffer.prototype% 。
具有其值为 [[Prototype]] 内部槽,其值为 %Object.prototype% 。
是一个 普通对象 。
没有 [[ArrayBufferData]] 或 [[ArrayBufferByteLength]]
内部槽。
25.2.5.1 获取 SharedArrayBuffer.prototype.byteLength
SharedArrayBuffer.prototype.byteLength
是一个 访问器属性 ,其 set 访问器函数为
undefined 。其 get 访问器函数在调用时执行以下步骤:
1. 令 O 为 this 值。
2. 执行 ? RequireInternalSlot (O ,
[[ArrayBufferData]] )。
3. 如果 IsSharedArrayBuffer (O )
为 false ,则抛出 TypeError 异常。
4. 令 length 为 ArrayBufferByteLength (O ,
seq-cst )。
5. 返回 𝔽 (length )。
25.2.5.2 SharedArrayBuffer.prototype.constructor
SharedArrayBuffer.prototype.constructor
的初始值是 %SharedArrayBuffer% 。
25.2.5.3 SharedArrayBuffer.prototype.grow (newLength )
此方法在调用时执行以下步骤:
1. 令 O 为 this 值。
2. 执行 ? RequireInternalSlot (O ,
[[ArrayBufferMaxByteLength]] )。
3. 如果 IsSharedArrayBuffer (O )
为 false ,则抛出 TypeError 异常。
4. 令 newByteLength 为 ? ToIndex (newLength )。
5. 令 hostHandled 为 ? HostGrowSharedArrayBuffer (O ,
newByteLength )。
6. 如果 hostHandled 为 handled ,则返回
undefined 。
7. 令 isLittleEndian 为 周围代理 的 代理记录 的 [[LittleEndian]] 字段的值。
8. 令 byteLengthBlock 为 O .[[ArrayBufferByteLengthData]] 。
9. 令 currentByteLengthRawBytes 为 GetRawBytesFromSharedBlock (byteLengthBlock ,
0, biguint64 , true , seq-cst )。
10. 令 newByteLengthRawBytes 为 NumericToRawBytes (biguint64 ,
ℤ (newByteLength ),
isLittleEndian )。
11. 重复,
a.
注:这是一个比较并交换循环,以确保同一个缓冲区的并行竞争增长是完全有序的,不会丢失,并且不会默默无闻地不做任何事。循环退出如果能够尝试增长无争用。
b. 令 currentByteLength 为 ℝ (RawBytesToNumeric (biguint64 ,
currentByteLengthRawBytes , isLittleEndian ))。
c. 如果 newByteLength =
currentByteLength ,则返回 undefined 。
d. 如果 newByteLength < currentByteLength
或 newByteLength > O .[[ArrayBufferMaxByteLength]]
var>,则抛出 RangeError 异常。
e. 令 byteLengthDelta 为 newByteLength -
currentByteLength 。
f. 如果不可能创建一个新的 共享数据块 值由
byteLengthDelta 字节组成,则抛出 RangeError 异常。
g. 注:在这里没有构造和使用新的 共享数据块 。可增长
SharedArrayBuffer 的可观察行为通过在构造时分配一个 max 大小的 共享数据块 来指定,并且此步骤捕获了实现内存不足时必须抛出
RangeError 的要求。
h. 令 readByteLengthRawBytes 为 AtomicCompareExchangeInSharedBlock (byteLengthBlock ,
0, 8, currentByteLengthRawBytes , newByteLengthRawBytes )。
i. 如果 ByteListEqual (readByteLengthRawBytes ,
currentByteLengthRawBytes ) 为 true ,则返回 undefined 。
j. 将 currentByteLengthRawBytes 设置为
readByteLengthRawBytes 。
注
禁止比较交换更新长度的虚假失败。如果新长度的边界检查通过且实现没有内存不足,则总是将 ReadModifyWriteSharedMemory
事件(即成功的比较交换)添加到 候选执行 中。
对 SharedArrayBuffer.prototype.grow 的并行调用是完全有序的。例如,考虑两个竞争调用:sab.grow(10)
和
sab.grow(20)
。两个调用中的一个保证会赢得竞争。调用 sab.grow(10)
将永远不会缩小 sab
,即使
sab.grow(20)
先发生;在这种情况下,它将抛出一个 RangeError。
25.2.5.4 获取 SharedArrayBuffer.prototype.growable
SharedArrayBuffer.prototype.growable
是一个 访问器属性 ,其 set 访问器函数为
undefined 。其 get 访问器函数在调用时执行以下步骤:
1. 令 O 为 this 值。
2. 执行 ? RequireInternalSlot (O ,
[[ArrayBufferData]] )。
3. 如果 IsSharedArrayBuffer (O )
为 false ,则抛出 TypeError 异常。
4. 如果 IsFixedLengthArrayBuffer (O )
为 false ,则返回 true ;否则返回 false 。
25.2.5.5 获取 SharedArrayBuffer.prototype.maxByteLength
SharedArrayBuffer.prototype.maxByteLength
是一个 访问器属性 ,其 set 访问器函数为
undefined 。其 get 访问器函数在调用时执行以下步骤:
1. 令 O 为 this 值。
2. 执行 ? RequireInternalSlot (O ,
[[ArrayBufferData]] )。
3. 如果 IsSharedArrayBuffer (O )
为 false ,则抛出 TypeError 异常。
4. 如果 IsFixedLengthArrayBuffer (O )
为 true,则
a. 令 length 为 O .[[ArrayBufferByteLength]] 。
5. 否则,
a. 令 length 为 O .[[ArrayBufferMaxByteLength]] 。
6. 返回 𝔽 (length )。
25.2.5.6 SharedArrayBuffer.prototype.slice (start ,
end )
此方法在调用时执行以下步骤:
1. 令 O 为 this 值。
2. 执行 ? RequireInternalSlot (O ,
[[ArrayBufferData]] )。
3. 如果 IsSharedArrayBuffer (O )
为 false ,则抛出 TypeError 异常。
4. 令 len 为 ArrayBufferByteLength (O ,
seq-cst )。
5. 令 relativeStart 为 ? ToIntegerOrInfinity (start )。
6. 如果 relativeStart = -∞,令 first 为 0。
7. 否则,如果 relativeStart < 0,令 first 为
max (len +
relativeStart , 0)。
8. 否则,令 first 为 min (relativeStart ,
len )。
9. 如果 end 是 undefined ,则令
relativeEnd 为 len ;否则令 relativeEnd 为 ? ToIntegerOrInfinity (end )。
10. 如果 relativeEnd = -∞,令 final 为 0。
11. 否则,如果 relativeEnd < 0,令 final 为
max (len +
relativeEnd , 0)。
12. 否则,令 final 为 min (relativeEnd ,
len )。
13. 令 newLen 为 max (final - first ,
0)。
14. 令 ctor 为 ? SpeciesConstructor (O , %SharedArrayBuffer% )。
15. 令 new 为 ? Construct (ctor , « 𝔽 (newLen ) »)。
16. 执行 ? RequireInternalSlot (new ,
[[ArrayBufferData]] )。
17. 如果 IsSharedArrayBuffer (new )
为 false ,则抛出 TypeError 异常。
18. 如果 new .[[ArrayBufferData]] 是
O .[[ArrayBufferData]] ,则抛出 TypeError 异常。
19. 如果 ArrayBufferByteLength (new ,
seq-cst ) < newLen ,则抛出 TypeError 异常。
20. 令 fromBuf 为 O .[[ArrayBufferData]] 。
21. 令 toBuf 为 new .[[ArrayBufferData]] 。
22. 执行 CopyDataBlockBytes (toBuf ,
0, fromBuf , first , newLen )。
23. 返回 new 。
25.2.5.7 SharedArrayBuffer.prototype [ @@toStringTag ]
@@toStringTag 属性的初始值是字符串值
"SharedArrayBuffer" 。
此属性具有以下特性 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
true }。
25.2.6 SharedArrayBuffer 实例的属性
SharedArrayBuffer 实例继承自 SharedArrayBuffer
原型对象 的属性。每个 SharedArrayBuffer 实例都有一个 [[ArrayBufferData]]
内部槽。非可增长的 SharedArrayBuffer 实例各自有一个 [[ArrayBufferByteLength]] 内部槽。可增长的
SharedArrayBuffer 实例各自有一个 [[ArrayBufferByteLengthData]] 内部槽和一个 [[ArrayBufferMaxByteLength]] 内部槽。
注
与 ArrayBuffer 实例不同,SharedArrayBuffer 实例从不分离。
25.2.7 可增长 SharedArrayBuffer 指南
注1
以下是为 ECMAScript 程序员在使用 可增长
SharedArrayBuffer 时的指南。
我们建议程序在可能的部署环境中进行测试。不同硬件设备之间的可用物理内存量差异很大。同样,不同硬件设备和操作系统之间的虚拟内存子系统也有很大差异。在 64 位桌面浏览器上运行无内存不足错误的应用程序可能会在
32 位移动浏览器上运行时内存不足。
在为 可增长
SharedArrayBuffer 选择 "maxByteLength" 选项的值时,我们建议选择应用程序所需的最小尺寸。我们建议
"maxByteLength" 不超过 1073741824 或 1GiB。
请注意,成功构建具有特定最大大小的 可增长
SharedArrayBuffer 并不保证未来的增长操作会成功。
并非所有对 可增长
SharedArrayBuffer 长度的加载都是同步的 seq-cst
加载。用于整数索引属性访问的边界检查的长度加载,例如 u8[idx]
,不是同步的。通常,在没有显式同步的情况下,一个属性访问在边界内并不意味着同一 代理
中的后续属性访问也在边界内。相比之下,通过 SharedArrayBuffer 上的 length
和 byteLength
获取器显式加载的长度是同步的。内建方法执行的检查 TypedArray 是否完全越界的长度加载也是同步的。
注2
以下是为实现 可增长
SharedArrayBuffer 的 ECMAScript 实现者提供的指南。
我们建议 可增长
SharedArrayBuffer 通过预先保留虚拟内存来实现就地增长。
因为增长操作可以与 可增长
SharedArrayBuffer 上的内存访问并行发生,所以 内存模型
的约束要求即使是无序访问也不会“撕裂”(它们的值的位不会混合)。实际上,这意味着 可增长
SharedArrayBuffer 的底层数据块不能通过复制来增长而不停止整个世界。我们不建议将停止整个世界作为实现策略,因为它引入了串行化点并且速度慢。
增长的内存必须从创建时起就显示为零,包括任何并行的竞争访问。这可以通过按需零填充的虚拟内存页面来实现,或者如果手动清零内存,则需要小心同步。
在 TypedArray 视图的可增长 SharedArrayBuffer 上的
整数索引 属性访问旨在类似于在非可增长 SharedArrayBuffer
的 TypedArray 视图上的访问进行优化,因为 整数索引
属性加载不会同步底层缓冲区的长度(参见上面的程序员指南)。例如,属性访问的边界检查仍然可以提升出循环。
实际上,在没有虚拟内存的 宿主 (例如那些在没有 MMU 的嵌入式设备上运行的宿主)上,通过复制来实现 可增长
SharedArrayBuffer 是很难的。在这样的 宿主 上,可增长 SharedArrayBuffer 的内存使用行为可能与具有虚拟内存的
宿主
有很大不同。这样的 宿主 应该清楚地向用户传达内存使用期望。
25.3 DataView 对象
25.3.1 DataView 对象的抽象操作
25.3.1.1 具有缓冲区见证记录的 DataView
具有缓冲区见证记录的 DataView 是一个
记录 值,用于封装
DataView 以及缓存的视图缓冲区的字节长度。当视图缓冲区是可增长的 SharedArrayBuffer 时,它用于帮助确保字节长度数据块的单一共享内存读取事件。
具有缓冲区见证记录的 DataView 包含 表
72 中列出的字段。
表 72: 具有缓冲区见证记录的
DataView 字段
字段名称
值
含义
[[Object]]
一个 DataView
其缓冲区的字节长度被加载的 DataView 对象。
[[CachedBufferByteLength]]
一个非负 整数 或 分离
创建 记录
时,对象的 [[ViewedArrayBuffer]] 的字节长度。
25.3.1.2 MakeDataViewWithBufferWitnessRecord (obj ,
order )
抽象操作 MakeDataViewWithBufferWitnessRecord 接受参数 obj (一个 DataView)和
order (seq-cst 或 unordered )并返回一个 具有缓冲区见证记录的
DataView 。它在调用时执行以下步骤:
1. 令 buffer 为 obj .[[ViewedArrayBuffer]] 。
2. 如果 IsDetachedBuffer (buffer )
为 true ,则
a. 令 byteLength 为 detached 。
3. 否则,
a. 令 byteLength 为 ArrayBufferByteLength (buffer ,
order )。
4. 返回 具有缓冲区见证记录的
DataView { [[Object]] : obj , [[CachedBufferByteLength]] : byteLength }。
25.3.1.3 GetViewByteLength (viewRecord )
抽象操作 GetViewByteLength 接受参数 viewRecord (一个 具有缓冲区见证记录的
DataView )并返回一个非负 整数 。它在调用时执行以下步骤:
1. 断言 : IsViewOutOfBounds (viewRecord )
为 false 。
2. 令 view 为 viewRecord .[[Object]] 。
3. 如果 view .[[ByteLength]] 不为
auto ,返回 view .[[ByteLength]] 。
4. 断言 : IsFixedLengthArrayBuffer (view .[[ViewedArrayBuffer]] ) 为 false 。
5. 令 byteOffset 为 view .[[ByteOffset]] 。
6. 令 byteLength 为 viewRecord .[[CachedBufferByteLength]] 。
7. 断言 : byteLength 不为
detached 。
8. 返回 byteLength - byteOffset 。
25.3.1.4 IsViewOutOfBounds (viewRecord )
抽象操作 IsViewOutOfBounds 接受参数 viewRecord (一个 具有缓冲区见证记录的
DataView )并返回一个布尔值。它在调用时执行以下步骤:
1. 令 view 为 viewRecord .[[Object]] 。
2. 令 bufferByteLength 为 viewRecord .[[CachedBufferByteLength]] 。
3. 断言 : 当且仅当 bufferByteLength 为
detached 时,IsDetachedBuffer (view .[[ViewedArrayBuffer]] ) 为 true 。
4. 如果 bufferByteLength 为
detached ,返回 true 。
5. 令 byteOffsetStart 为 view .[[ByteOffset]] 。
6. 如果 view .[[ByteLength]] 为
auto ,则
a. 令 byteOffsetEnd 为 bufferByteLength 。
7. 否则,
a. 令 byteOffsetEnd 为 byteOffsetStart +
view .[[ByteLength]] 。
8. 如果 byteOffsetStart > bufferByteLength 或
byteOffsetEnd > bufferByteLength ,返回 true 。
9. 注:长度为 0 的 DataView 不被认为是越界的。
10. 返回 false 。
25.3.1.5 GetViewValue (view , requestIndex ,
isLittleEndian , type )
抽象操作 GetViewValue 接受参数 view (一个 ECMAScript
语言值 )、requestIndex (一个 ECMAScript
语言值 )、isLittleEndian (一个 ECMAScript
语言值 )和 type (一个 TypedArray 元素类型 ),并返回包含 Number 或
BigInt 的 正常完成记录 ,或
抛出完成记录 。它被
DataView 实例上的函数用来从视图的缓冲区中检索值。它在调用时执行以下步骤:
1. 执行 ? RequireInternalSlot (view ,
[[DataView]] )。
2. 断言 : view 具有 [[ViewedArrayBuffer]] 内部槽。
3. 令 getIndex 为 ? ToIndex (requestIndex )。
4. 将 isLittleEndian 设置为 ToBoolean (isLittleEndian )。
5. 令 viewOffset 为 view .[[ByteOffset]] 。
6. 令 viewRecord 为 MakeDataViewWithBufferWitnessRecord (view ,
unordered )。
7. 注:当 view 的支撑缓冲区是 可增长
SharedArrayBuffer 时,边界检查不是同步操作。
8. 如果 IsViewOutOfBounds (viewRecord )
为 true ,抛出 TypeError 异常。
9. 令 viewSize 为 GetViewByteLength (viewRecord )。
10. 令 elementSize 为 表 71 中指定的元素类型
type 的元素大小值。
11. 如果 getIndex + elementSize >
viewSize ,抛出 RangeError 异常。
12. 令 bufferIndex 为 getIndex +
viewOffset 。
13. 返回 GetValueFromBuffer (view .[[ViewedArrayBuffer]] , bufferIndex , type ,
false , unordered , isLittleEndian )。
25.3.1.6 SetViewValue (view , requestIndex ,
isLittleEndian , type , value )
抽象操作 SetViewValue 接受参数 view (一个 ECMAScript
语言值 )、requestIndex (一个 ECMAScript
语言值 )、isLittleEndian (一个 ECMAScript
语言值 )、type (一个 TypedArray 元素类型 )和
value (一个 ECMAScript 语言值 ),并返回包含
undefined 的 正常完成记录 或
抛出完成记录 。它被
DataView 实例上的函数用来将值存储到视图的缓冲区中。它在调用时执行以下步骤:
1. 执行 ? RequireInternalSlot (view ,
[[DataView]] )。
2. 断言 : view 具有 [[ViewedArrayBuffer]] 内部槽。
3. 令 getIndex 为 ? ToIndex (requestIndex )。
4. 如果 IsBigIntElementType (type )
为 true ,则令 numberValue 为 ? ToBigInt (value )。
5. 否则,令 numberValue 为 ? ToNumber (value )。
6. 将 isLittleEndian 设置为 ToBoolean (isLittleEndian )。
7. 令 viewOffset 为 view .[[ByteOffset]] 。
8. 令 viewRecord 为 MakeDataViewWithBufferWitnessRecord (view ,
unordered )。
9. 注:当 view 的支撑缓冲区是 可增长
SharedArrayBuffer 时,边界检查不是同步操作。
10. 如果 IsViewOutOfBounds (viewRecord )
为 true ,抛出 TypeError 异常。
11. 令 viewSize 为 GetViewByteLength (viewRecord )。
12. 令 elementSize 为 表 71 中指定的元素类型
type 的元素大小值。
13. 如果 getIndex + elementSize >
viewSize ,抛出 RangeError 异常。
14. 令 bufferIndex 为 getIndex +
viewOffset 。
15. 执行 SetValueInBuffer (view .[[ViewedArrayBuffer]] , bufferIndex , type ,
numberValue , false , unordered ,
isLittleEndian )。
16. 返回 undefined 。
25.3.2 DataView 构造函数
DataView 构造函数 :
是 %DataView% 。
是 全局对象 的 "DataView"
属性的初始值。
作为 构造函数 调用时,创建并初始化一个新的 DataView。
不应作为函数调用,否则会抛出异常。
可以用作类定义的 extends
子句的值。继承指定 DataView 行为的子类 构造函数 必须包含对 DataView 构造函数 的
super
调用,以创建和初始化具有支持 DataView.prototype
内置方法的内部状态的子类实例。
25.3.2.1 DataView (buffer [ , byteOffset [ ,
byteLength ] ])
此函数在调用时执行以下步骤:
1. 如果 NewTarget 为 undefined ,抛出
TypeError 异常。
2. 执行 ? RequireInternalSlot (buffer ,
[[ArrayBufferData]] )。
3. 令 offset 为 ? ToIndex (byteOffset )。
4. 如果 IsDetachedBuffer (buffer )
为 true ,抛出 TypeError 异常。
5. 令 bufferByteLength 为 ArrayBufferByteLength (buffer ,
seq-cst )。
6. 如果 offset > bufferByteLength ,抛出
RangeError 异常。
7. 令 bufferIsFixedLength 为 IsFixedLengthArrayBuffer (buffer )。
8. 如果 byteLength 为 undefined ,则
a. 如果 bufferIsFixedLength 为 true ,则
i. 令 viewByteLength 为 bufferByteLength
- offset 。
b. 否则,
i. 令 viewByteLength 为
auto 。
9. 否则,
a. 令 viewByteLength 为 ? ToIndex (byteLength )。
b. 如果 offset + viewByteLength >
bufferByteLength ,抛出 RangeError 异常。
10. 令 O 为 ? OrdinaryCreateFromConstructor (NewTarget,
"%DataView.prototype%" , « [[DataView]] , [[ViewedArrayBuffer]] , [[ByteLength]] , [[ByteOffset]] »)。
11. 如果 IsDetachedBuffer (buffer )
为 true ,抛出 TypeError 异常。
12. 将 bufferByteLength 设置为 ArrayBufferByteLength (buffer ,
seq-cst )。
13. 如果 offset > bufferByteLength ,抛出
RangeError 异常。
14. 如果 byteLength 不为 undefined ,则
a. 如果 offset + viewByteLength >
bufferByteLength ,抛出 RangeError 异常。
15. 将 O .[[ViewedArrayBuffer]]
设置为 buffer 。
16. 将 O .[[ByteLength]] 设置为
viewByteLength 。
17. 将 O
.[[ByteOffset]] 设置为 offset 。
18. 返回 O 。
25.3.3 DataView 构造函数的属性
DataView 构造函数 :
25.3.3.1 DataView.prototype
DataView.prototype
的初始值是 DataView
原型对象 。
该属性具有以下特性 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
false }.
25.3.4 DataView 原型对象的属性
DataView 原型对象 :
是 %DataView.prototype% 。
具有一个 [[Prototype]] 内部槽,其值为 %Object.prototype% 。
是一个 普通对象 。
没有 [[DataView]] 、[[ViewedArrayBuffer]] 、[[ByteLength]] 或 [[ByteOffset]] 内部槽。
25.3.4.1 get DataView.prototype.buffer
DataView.prototype.buffer
是一个 访问器属性 ,其 set 访问器函数为
undefined 。其 get 访问器函数在调用时执行以下步骤:
1. 令 O 为 this 值。
2. 执行 ? RequireInternalSlot (O ,
[[DataView]] )。
3. 断言 : O 具有一个 [[ViewedArrayBuffer]] 内部槽。
4. 令 buffer 为 O .[[ViewedArrayBuffer]] 。
5. 返回 buffer 。
25.3.4.2 get DataView.prototype.byteLength
DataView.prototype.byteLength
是一个 访问器属性 ,其 set 访问器函数为
undefined 。其 get 访问器函数在调用时执行以下步骤:
1. 令 O 为 this 值。
2. 执行 ? RequireInternalSlot (O ,
[[DataView]] )。
3. 断言 : O 具有一个 [[ViewedArrayBuffer]] 内部槽。
4. 令 viewRecord 为 MakeDataViewWithBufferWitnessRecord (O ,
seq-cst )。
5. 如果 IsViewOutOfBounds (viewRecord )
为 true ,抛出 TypeError 异常。
6. 令 size 为 GetViewByteLength (viewRecord )。
7. 返回 𝔽 (size )。
25.3.4.3 get DataView.prototype.byteOffset
DataView.prototype.byteOffset
是一个 访问器属性 ,其 set 访问器函数为
undefined 。其 get 访问器函数在调用时执行以下步骤:
1. 令 O 为 this 值。
2. 执行 ? RequireInternalSlot (O ,
[[DataView]] )。
3. 断言 : O 具有一个 [[ViewedArrayBuffer]] 内部槽。
4. 令 viewRecord 为 MakeDataViewWithBufferWitnessRecord (O ,
seq-cst )。
5. 如果 IsViewOutOfBounds (viewRecord )
为 true ,抛出 TypeError 异常。
6. 令 offset 为 O .[[ByteOffset]] 。
7. 返回 𝔽 (offset )。
25.3.4.4 DataView.prototype.constructor
DataView.prototype.constructor 的初始值是 %DataView% 。
25.3.4.5 DataView.prototype.getBigInt64 ( byteOffset [ ,
littleEndian ] )
该方法在调用时执行以下步骤:
1. 令 v 为 this 值。
2. 返回 ? GetViewValue (v , byteOffset ,
littleEndian , bigint64 )。
25.3.4.6 DataView.prototype.getBigUint64 ( byteOffset [ ,
littleEndian ] )
该方法在调用时执行以下步骤:
1. 令 v 为 this 值。
2. 返回 ? GetViewValue (v , byteOffset ,
littleEndian , biguint64 )。
25.3.4.7 DataView.prototype.getFloat32 ( byteOffset [ ,
littleEndian ] )
该方法在调用时执行以下步骤:
1. 令 v 为 this 值。
2. 如果 littleEndian 未提供,将 littleEndian 设置为
false 。
3. 返回 ? GetViewValue (v , byteOffset ,
littleEndian , float32 )。
25.3.4.8 DataView.prototype.getFloat64 ( byteOffset [ ,
littleEndian ] )
该方法在调用时执行以下步骤:
1. 令 v 为 this 值。
2. 如果 littleEndian 未提供,将 littleEndian 设置为
false 。
3. 返回 ? GetViewValue (v , byteOffset ,
littleEndian , float64 )。
25.3.4.9 DataView.prototype.getInt8 ( byteOffset )
该方法在调用时执行以下步骤:
1. 令 v 为 this 值。
2. 返回 ? GetViewValue (v , byteOffset ,
true , int8 )。
25.3.4.10 DataView.prototype.getInt16 ( byteOffset [ ,
littleEndian ] )
该方法在调用时执行以下步骤:
1. 令 v 为 this 值。
2. 如果 littleEndian 未提供,将 littleEndian 设置为
false 。
3. 返回 ? GetViewValue (v , byteOffset ,
littleEndian , int16 )。
25.3.4.11 DataView.prototype.getInt32 ( byteOffset [ ,
littleEndian ] )
该方法在调用时执行以下步骤:
1. 令 v 为 this 值。
2. 如果 littleEndian 未提供,将 littleEndian 设置为
false 。
3. 返回 ? GetViewValue (v , byteOffset ,
littleEndian , int32 )。
25.3.4.12 DataView.prototype.getUint8 ( byteOffset )
该方法在调用时执行以下步骤:
1. 令 v 为 this 值。
2. 返回 ? GetViewValue (v , byteOffset ,
true , uint8 )。
25.3.4.13 DataView.prototype.getUint16 ( byteOffset [ ,
littleEndian ] )
该方法在调用时执行以下步骤:
1. 令 v 为 this 值。
2. 如果 littleEndian 未提供,将 littleEndian 设置为
false 。
3. 返回 ? GetViewValue (v , byteOffset ,
littleEndian , uint16 )。
25.3.4.14 DataView.prototype.getUint32 ( byteOffset [ ,
littleEndian ] )
该方法在调用时执行以下步骤:
1. 令 v 为 this 值。
2. 如果 littleEndian 未提供,将 littleEndian 设置为
false 。
3. 返回 ? GetViewValue (v , byteOffset ,
littleEndian , uint32 )。
25.3.4.15 DataView.prototype.setBigInt64 ( byteOffset ,
value [ , littleEndian ] )
该方法在调用时执行以下步骤:
1. 令 v 为 this 值。
2. 返回 ? SetViewValue (v , byteOffset ,
littleEndian , bigint64 , value )。
25.3.4.16 DataView.prototype.setBigUint64 ( byteOffset ,
value [ , littleEndian ] )
该方法在调用时执行以下步骤:
1. 令 v 为 this 值。
2. 返回 ? SetViewValue (v , byteOffset ,
littleEndian , biguint64 , value )。
25.3.4.17 DataView.prototype.setFloat32 ( byteOffset ,
value [ , littleEndian ] )
该方法在调用时执行以下步骤:
1. 令 v 为 this 值。
2. 如果 littleEndian 未提供,将 littleEndian 设置为
false 。
3. 返回 ? SetViewValue (v , byteOffset ,
littleEndian , float32 , value )。
25.3.4.18 DataView.prototype.setFloat64 ( byteOffset ,
value [ , littleEndian ] )
该方法在调用时执行以下步骤:
1. 令 v 为 this 值。
2. 如果 littleEndian 未提供,将 littleEndian 设置为
false 。
3. 返回 ? SetViewValue (v , byteOffset ,
littleEndian , float64 , value )。
25.3.4.19 DataView.prototype.setInt8 ( byteOffset ,
value )
该方法在调用时执行以下步骤:
1. 令 v 为 this 值。
2. 返回 ? SetViewValue (v , byteOffset ,
true , int8 , value )。
25.3.4.20 DataView.prototype.setInt16 ( byteOffset ,
value [ , littleEndian ] )
该方法在调用时执行以下步骤:
1. 令 v 为 this 值。
2. 如果 littleEndian 未提供,将 littleEndian 设置为
false 。
3. 返回 ? SetViewValue (v , byteOffset ,
littleEndian , int16 , value )。
25.3.4.21 DataView.prototype.setInt32 ( byteOffset ,
value [ , littleEndian ] )
该方法在调用时执行以下步骤:
1. 令 v 为 this 值。
2. 如果 littleEndian 未提供,将 littleEndian 设置为
false 。
3. 返回 ? SetViewValue (v , byteOffset ,
littleEndian , int32 , value )。
25.3.4.22 DataView.prototype.setUint8 ( byteOffset ,
value )
该方法在调用时执行以下步骤:
1. 令 v 为 this 值。
2. 返回 ? SetViewValue (v , byteOffset ,
true , uint8 , value )。
25.3.4.23 DataView.prototype.setUint16 ( byteOffset ,
value [ , littleEndian ] )
该方法在调用时执行以下步骤:
1. 令 v 为 this 值。
2. 如果 littleEndian 未提供,将 littleEndian 设置为
false 。
3. 返回 ? SetViewValue (v , byteOffset ,
littleEndian , uint16 , value )。
25.3.4.24 DataView.prototype.setUint32 ( byteOffset ,
value [ , littleEndian ] )
该方法在调用时执行以下步骤:
1. 令 v 为 this 值。
2. 如果 littleEndian 未提供,将 littleEndian 设置为
false 。
3. 返回 ? SetViewValue (v , byteOffset ,
littleEndian , uint32 , value )。
25.3.4.25 DataView.prototype [ @@toStringTag ]
@@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"
属性的初始值。
是一个普通对象 。
具有其值为%Object.prototype% 的
[[Prototype]] 内部槽位。
没有 [[Construct]] 内部方法;不能使用 new
运算符作为构造函数 。
没有 [[Call]] 内部方法;不能作为函数调用。
Atomics 对象提供对共享内存数组单元进行不可分割(原子)操作的函数,以及让代理 等待和调度原始事件的函数。当按规则使用时,Atomics
函数允许通过共享内存通信的多代理 程序即使在并行 CPU 上也能按预期顺序执行。控制共享内存通信的规则由下面定义的内存模型 提供。
注
有关在 ECMAScript 中编程和实现共享内存的信息指南,请参见内存模型 部分末尾的注释。
25.4.1 Waiter 记录
Waiter 记录 是一个用于表示对 Atomics.wait
或
Atomics.waitAsync
的特定调用的记录 值。
Waiter 记录具有表 73 中列出的字段。
表 73: Waiter 记录 字段
字段名称
值
含义
[[AgentSignifier]]
一个代理标识符
调用Atomics.wait
或Atomics.waitAsync
的代理 。
[[PromiseCapability]]
一个PromiseCapability
记录 或阻塞
如果表示对Atomics.waitAsync
的调用,则为生成的 Promise,否则为阻塞 。
[[TimeoutTime]]
一个非负的扩展数学值
最早可能触发超时的时间;使用时间值 计算。
[[Result]]
"ok" 或"timed-out"
调用的返回值。
25.4.2 WaiterList 记录
WaiterList 记录 用于解释通过
Atomics.wait
、Atomics.waitAsync
和 Atomics.notify
对代理 的等待和通知。
WaiterList 记录具有表 74 中列出的字段。
表 74: WaiterList 记录 字段
字段名称
值
含义
[[Waiters]]
Waiter
记录 的列表
调用Atomics.wait
或Atomics.waitAsync
等待的位置与此 WaiterList 关联。
[[MostRecentLeaveEvent]]
同步事件 或空
最近离开临界区 的事件,如果从未进入其临界区 ,则为空 。
在一个 WaiterList 中可以有多个具有相同代理标识符 的Waiter 记录 。
代理集群 拥有 WaiterList 记录的存储;该存储由
(块 , i ) 索引,其中 块 是共享数据块 ,i 是 块
内存中的字节偏移量。WaiterList 记录是代理 无关的:在任何代理集群 中的代理 ,按 (块 ,
i ) 查找 WaiterList 记录将得到相同的 WaiterList 记录。
每个 WaiterList 记录都有一个控制在评估期间对该 WaiterList 记录的独占访问的临界区 。一次只能有一个代理 进入 WaiterList 记录的临界区。进入和离开 WaiterList
记录的临界区由抽象操作 EnterCriticalSection 和LeaveCriticalSection 控制。对
WaiterList 记录的操作——添加和删除等待的代理 、遍历代理 列表、挂起和通知列表上的代理 、设置和检索同步事件 ——只能由进入 WaiterList
记录的临界区的代理 执行。
25.4.3 Atomics 的抽象操作
25.4.3.1 ValidateIntegerTypedArray ( typedArray ,
waitable )
抽象操作 ValidateIntegerTypedArray 接受参数 typedArray (一个ECMAScript 语言值 )和
waitable (一个布尔值),并返回一个包含 带缓冲区见证记录的
TypedArray 的正常完成记录,或一个抛出完成记录 。调用时执行以下步骤:
1. 令 taRecord 为 ? ValidateTypedArray (typedArray ,
unordered )。
2. 注意:当 typedArray 的支持缓冲区是可增长的
SharedArrayBuffer 时,边界检查不是同步操作。
3. 如果 waitable 为 true ,则
a. 如果 typedArray .[[TypedArrayName]] 既不是 "Int32Array" 也不是
"BigInt64Array" ,则抛出 TypeError 异常。
4. 否则,
a. 令 type 为 TypedArrayElementType (typedArray )。
b. 如果 IsUnclampedIntegerElementType (type )
为 false 且 IsBigIntElementType (type )
为 false ,则抛出 TypeError 异常。
5. 返回 taRecord 。
25.4.3.2 ValidateAtomicAccess ( taRecord ,
requestIndex
)
抽象操作 ValidateAtomicAccess 接受参数 taRecord (一个带缓冲区见证记录的
TypedArray )和 requestIndex (一个ECMAScript
语言值 ),并返回一个包含 一个整数 的正常完成记录,或一个抛出完成记录 。调用时执行以下步骤:
1. 令 length 为 ? TypedArrayLength (taRecord )。
2. 令 accessIndex 为 ? ToIndex (requestIndex )。
3. 断言 :accessIndex ≥ 0。
4. 如果 accessIndex ≥ length ,抛出一个
RangeError 异常。
5. 令 typedArray 为 taRecord .[[Object]] 。
6. 令 elementSize 为 TypedArrayElementSize (typedArray )。
7. 令 offset 为 typedArray .[[ByteOffset]] 。
8. 返回 (accessIndex × elementSize ) +
offset 。
25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray (
typedArray ,
requestIndex [ , waitable ] )
抽象操作 ValidateAtomicAccessOnIntegerTypedArray 接受参数 typedArray
(一个ECMAScript 语言值 )和
requestIndex (一个ECMAScript
语言值 )以及可选参数 waitable (一个布尔值),并返回一个包含 一个整数 的正常完成记录,或一个抛出
完成记录 。调用时执行以下步骤:
1. 如果 waitable 未提供,则将 waitable 设置为
false 。
2. 令 taRecord 为 ? ValidateIntegerTypedArray (typedArray ,
waitable )。
3. 返回 ? ValidateAtomicAccess (taRecord ,
requestIndex )。
25.4.3.4 RevalidateAtomicAccess ( typedArray ,
byteIndexInBuffer )
抽象操作 RevalidateAtomicAccess 接受参数 typedArray (一个TypedArray )和
byteIndexInBuffer (一个整数 ),并返回一个包含
unused 的正常完成记录,或一个抛出完成记录 。此操作在
Atomics 方法中完成所有参数强制转换后重新验证用于原子操作的支持缓冲区内的索引,因为参数强制转换可能具有任意的副作用,可能导致缓冲区超出范围。当 typedArray 的支持缓冲区是
SharedArrayBuffer 时,此操作不会抛出异常。调用时执行以下步骤:
1. 令 taRecord 为 MakeTypedArrayWithBufferWitnessRecord (typedArray ,
unordered )。
2. 注意:当 typedArray 的支持缓冲区是可增长的
SharedArrayBuffer 时,边界检查不是同步操作。
3. 如果 IsTypedArrayOutOfBounds (taRecord )
为 true ,抛出一个 TypeError 异常。
4. 断言 :byteIndexInBuffer ≥
typedArray .[[ByteOffset]] 。
5. 如果 byteIndexInBuffer ≥ taRecord .[[CachedBufferByteLength]] ,抛出一个 RangeError 异常。
6. 返回 unused 。
25.4.3.5 GetWaiterList ( block , i )
抽象操作 GetWaiterList 接受参数 block (一个共享数据块 )和 i (一个非负的整数 ,它可以被 4
整除)并返回一个WaiterList 记录 。调用时执行以下步骤:
1. 断言 :i 和 i + 3 是
block 内存中有效的字节偏移量。
2. 返回由对 (block , i ) 引用的WaiterList 记录 。
25.4.3.6 EnterCriticalSection ( WL )
抽象操作 EnterCriticalSection 接受参数 WL (一个WaiterList
记录 )并返回 unused 。调用时执行以下步骤:
1. 断言 :周围代理 未在任何WaiterList 记录 的临界区 中。
2. 等待直到没有代理 在WL 的临界区 ,然后进入WL 的临界区 (不允许任何其他代理 进入)。
3. 如果 WL .[[MostRecentLeaveEvent]] 不是 empty ,则
a. 注意:至少一次进入其临界区 的WL 有一个由LeaveCriticalSection 设置的同步事件 。
b. 令 execution 为周围代理 的代理记录 的 [[CandidateExecution]] 字段。
c. 令 eventsRecord 为 execution .[[EventsRecords]] 中的代理事件记录 ,其 [[AgentSignifier]] 是 AgentSignifier ()。
d. 令 enterEvent 为一个新的同步事件 。
e. 将 enterEvent 附加到 eventsRecord .[[EventList]] 。
f. 将 (WL .[[MostRecentLeaveEvent]] , enterEvent ) 附加到
eventsRecord .[[AgentSynchronizesWith]] 。
4. 返回 unused 。
当一个代理 试图进入临界区 时必须等待另一个代理 离开它时,EnterCritical Section 有争用 。当没有争用时,可以观察到 EnterCriticalSection 调用的 FIFO
顺序。当有争用时,实现可以选择任意顺序,但不能导致一个代理 无限期等待。
25.4.3.7 LeaveCriticalSection ( WL )
抽象操作 LeaveCriticalSection 接受参数 WL (一个WaiterList
记录 )并返回 unused 。调用时执行以下步骤:
1. 断言 :周围代理 在
WL 的临界区 中。
2. 令 execution 为周围代理 的代理记录 的 [[CandidateExecution]] 字段。
3. 令 eventsRecord 为 execution .[[EventsRecords]] 中的代理事件记录 ,其 [[AgentSignifier]] 是 AgentSignifier ()。
4. 令 leaveEvent 为一个新的同步事件 。
5. 将 leaveEvent 附加到 eventsRecord .[[EventList]] 。
6. 将 WL .[[MostRecentLeaveEvent]]
设置为 leaveEvent 。
7. 离开 WL 的临界区 。
8. 返回 unused 。
25.4.3.8 AddWaiter ( WL , waiterRecord )
抽象操作 AddWaiter 接受参数 WL (一个WaiterList 记录 )和
waiterRecord (一个Waiter 记录 )并返回
unused 。调用时执行以下步骤:
1. 断言 :周围代理 在
WL 的临界区 中。
2. 断言 :WL .[[Waiters]] 中没有Waiter 记录 ,其 [[PromiseCapability]] 字段是 waiterRecord .[[PromiseCapability]] ,且其 [[AgentSignifier]] 字段是
waiterRecord .[[AgentSignifier]] 。
3. 将 waiterRecord 附加到 WL .[[Waiters]] 。
4. 返回 unused 。
25.4.3.9 RemoveWaiter ( WL , waiterRecord )
抽象操作 RemoveWaiter 接受参数 WL (一个WaiterList 记录 )和
waiterRecord (一个Waiter 记录 )并返回
unused 。调用时执行以下步骤:
1. 断言 :周围代理 在
WL 的临界区 中。
2. 断言 :WL .[[Waiters]] 包含 waiterRecord 。
3. 从 WL .[[Waiters]] 中移除
waiterRecord 。
4. 返回 unused 。
25.4.3.10 RemoveWaiters ( WL , c )
抽象操作 RemoveWaiters 接受参数 WL (一个WaiterList 记录 )和
c (一个非负的整数 或 +∞)并返回一个列表 ,其中包含Waiter
记录 。调用时执行以下步骤:
1. 断言 :周围代理 在
WL 的临界区 中。
2. 令 len 为 WL .[[Waiters]] 中的元素数量。
3. 令 n 为 min (c , len )。
4. 令 L 为一个列表 ,其元素为
WL .[[Waiters]] 的前 n 个元素。
5. 移除 WL .[[Waiters]] 的前
n 个元素。
6. 返回 L 。
25.4.3.11 SuspendThisAgent ( WL , waiterRecord )
抽象操作 SuspendThisAgent 接受参数 WL (一个WaiterList 记录 )和
waiterRecord (一个Waiter 记录 )并返回
unused 。调用时执行以下步骤:
1. 断言 :周围代理 在
WL 的临界区 中。
2. 断言 :WL .[[Waiters]] 包含 waiterRecord 。
3. 令 thisAgent 为 AgentSignifier ()。
4. 断言 :waiterRecord .[[AgentSignifier]] 是 thisAgent 。
5. 断言 :waiterRecord .[[PromiseCapability]] 是 blocking 。
6. 断言 :AgentCanSuspend () 是
true 。
7. 执行 LeaveCriticalSection (WL )
并挂起 周围代理 ,直到时间为
waiterRecord .[[TimeoutTime]] ,以这样的方式执行组合操作:在退出临界区 后但在挂起生效前到达的通知不会丢失。周围代理 只能因超时或其他代理 调用
NotifyWaiter 以 WL 和
thisAgent 为参数(即通过调用 Atomics.notify
)而从挂起中唤醒。
8. 执行 EnterCriticalSection (WL )。
9. 返回 unused 。
25.4.3.12 NotifyWaiter ( WL , waiterRecord )
抽象操作 NotifyWaiter 接受参数 WL (一个WaiterList 记录 )和
waiterRecord (一个Waiter 记录 )并返回
unused 。调用时执行以下步骤:
1. 断言 :周围代理 在
WL 的临界区 中。
2. 如果 waiterRecord .[[PromiseCapability]] 是 blocking ,则
a. 唤醒其标识符为 waiterRecord .[[AgentSignifier]] 的代理 。
b. 注意:这会导致代理 在SuspendThisAgent 中恢复执行。
3. 否则,如果AgentSignifier () 是
waiterRecord .[[AgentSignifier]] ,则
a. 令 promiseCapability 为 waiterRecord .[[PromiseCapability]] 。
b. 执行 ! Call (promiseCapability .[[Resolve]] , undefined , « waiterRecord .[[Result]] »)。
4. 否则,
a. 执行 EnqueueResolveInAgentJob (waiterRecord .[[AgentSignifier]] , waiterRecord .[[PromiseCapability]] , waiterRecord .[[Result]] )。
5. 返回 unused 。
注
一个代理 不得以任何方式访问另一个代理 的 promise
能力,除了将其传递给宿主 。
25.4.3.13 EnqueueResolveInAgentJob ( agentSignifier ,
promiseCapability , resolution )
抽象操作 EnqueueResolveInAgentJob 接受参数 agentSignifier (一个代理标识符 ),promiseCapability (一个PromiseCapability 记录 ),以及
resolution (一个ECMAScript 语言值 ),并返回
unused 。调用时执行以下步骤:
1. 令 resolveJob 为一个新的 Job 抽象闭包 ,不带参数,捕获
agentSignifier 、promiseCapability 和 resolution ,并在调用时执行以下步骤:
a. 断言 :AgentSignifier () 是
agentSignifier 。
b. 执行 ! Call (promiseCapability .[[Resolve]] , undefined , « resolution »)。
c. 返回 unused 。
2. 令 realmInTargetAgent 为 ! GetFunctionRealm (promiseCapability .[[Resolve]] )。
3. 断言 :agentSignifier 是
realmInTargetAgent .[[AgentSignifier]] 。
4. 执行 HostEnqueueGenericJob (resolveJob ,
realmInTargetAgent )。
5. 返回 unused 。
25.4.3.14 DoWait ( mode , typedArray , index ,
value , timeout )
抽象操作 DoWait 接受参数 mode (sync 或
async ),typedArray (一个 ECMAScript
语言值 ),index (一个 ECMAScript
语言值 ),value (一个 ECMAScript
语言值 ),以及 timeout (一个 ECMAScript
语言值 ),并返回 正常完成记录 ,包含一个对象、"not-equal" 、"timed-out"
或 "ok" ,或者 抛出完成记录 。调用时执行以下步骤:
1. 令 taRecord 为 ? ValidateIntegerTypedArray (typedArray ,
true )。
2. 令 buffer 为 taRecord .[[Object]] .[[ViewedArrayBuffer]] 。
3. 如果 IsSharedArrayBuffer (buffer )
为 false ,抛出一个 TypeError 异常。
4. 令 i 为 ? ValidateAtomicAccess (taRecord , index )。
5. 令 arrayTypeName 为 typedArray .[[TypedArrayName]] 。
6. 如果 arrayTypeName 是
"BigInt64Array" ,令 v 为 ? ToBigInt64 (value )。
7. 否则,令 v 为 ? ToInt32 (value )。
8. 令 q 为 ? ToNumber (timeout )。
9. 如果 q 是 NaN 或
+∞ 𝔽 ,令 t 为 +∞;否则如果 q 是
-∞ 𝔽 ,令 t 为 0;否则令 t 为 max (ℝ (q ), 0)。
10. 如果 mode 是 sync 且 AgentCanSuspend () 为
false ,抛出一个 TypeError 异常。
11. 令 block 为 buffer .[[ArrayBufferData]] 。
12. 令 offset 为 typedArray .[[ByteOffset]] 。
13. 令 byteIndexInBuffer 为 (i × 4) +
offset 。
14. 令 WL 为 GetWaiterList (block ,
byteIndexInBuffer )。
15. 如果 mode 是 sync ,则
a. 令 promiseCapability 为
blocking 。
b. 令 resultObject 为 undefined 。
16. 否则,
a. 令 promiseCapability 为 ! NewPromiseCapability (%Promise% )。
b. 令 resultObject 为 OrdinaryObjectCreate (%Object.prototype% )。
17. 执行 EnterCriticalSection (WL )。
18. 令 elementType 为 TypedArrayElementType (typedArray )。
19. 令 w 为 GetValueFromBuffer (buffer ,
byteIndexInBuffer , elementType , true ,
seq-cst )。
20. 如果 v ≠ w ,则
a. 执行 LeaveCriticalSection (WL )。
b. 如果 mode 是 sync ,返回
"not-equal" 。
c. 执行 ! CreateDataPropertyOrThrow (resultObject ,
"async" , false )。
d. 执行 ! CreateDataPropertyOrThrow (resultObject ,
"value" , "not-equal" )。
e. 返回 resultObject 。
21. 如果 t 是 0 且 mode 是
async ,则
a. 注意:同步立即超时没有特殊处理。异步立即超时有特殊处理,以快速失败并避免不必要的 Promise 任务。
b. 执行 LeaveCriticalSection (WL )。
c. 执行 ! CreateDataPropertyOrThrow (resultObject ,
"async" , false )。
d. 执行 ! CreateDataPropertyOrThrow (resultObject ,
"value" , "timed-out" )。
e. 返回 resultObject 。
22. 令 thisAgent 为 AgentSignifier ()。
23. 令 now 为标识当前时间的 时间值 (UTC)。
24. 令 additionalTimeout 为一个 实现定义的 非负 数学值 。
25. 令 timeoutTime 为 ℝ (now ) + t +
additionalTimeout 。
26. 注意:当 t 是 +∞ 时,timeoutTime 也是 +∞。
27. 令 waiterRecord 为一个新的 Waiter Record { [[AgentSignifier]] : thisAgent , [[PromiseCapability]] : promiseCapability , [[TimeoutTime]] : timeoutTime , [[Result]] :
"ok" }。
28. 执行 AddWaiter (WL ,
waiterRecord )。
29. 如果 mode 是 sync ,则
a. 执行 SuspendThisAgent (WL ,
waiterRecord )。
30. 否则如果 timeoutTime 是 有限的 ,则
a. 执行 EnqueueAtomicsWaitAsyncTimeoutJob (WL ,
waiterRecord )。
31. 执行 LeaveCriticalSection (WL )。
32. 如果 mode 是 sync ,返回
waiterRecord .[[Result]] 。
33. 执行 ! CreateDataPropertyOrThrow (resultObject ,
"async" , true )。
34. 执行 ! CreateDataPropertyOrThrow (resultObject ,
"value" , promiseCapability .[[Promise]] )。
35. 返回 resultObject 。
注
additionalTimeout 允许实现按需要填充超时,例如减少电量消耗或粗化计时器分辨率以缓解计时攻击。此值可能在每次调用 DoWait 时有所不同。
25.4.3.15 EnqueueAtomicsWaitAsyncTimeoutJob ( WL ,
waiterRecord )
当调用时,抽象操作 EnqueueAtomicsWaitAsyncTimeoutJob 接受参数 WL (一个 WaiterList Record )和
waiterRecord (一个 Waiter Record ),并返回
unused 。它执行以下步骤:
1. 令 timeoutJob 为一个新的 Job Abstract Closure ,没有参数,它捕获
WL 和 waiterRecord 并在调用时执行以下步骤:
a. 执行 EnterCriticalSection (WL )。
b. 如果 WL 的 [[Waiters]] 包含
waiterRecord ,则:
i. 令 timeOfJobExecution 为标识当前时间的 时间值 (UTC)。
ii. 断言 :ℝ (timeOfJobExecution )
≥ waiterRecord 的 [[TimeoutTime]] (忽略 时间值
的潜在非单调性)。
iii. 将 waiterRecord 的 [[Result]] 设置为 "timed-out" 。
iv. 执行 RemoveWaiter (WL ,
waiterRecord )。
v. 执行 NotifyWaiter (WL ,
waiterRecord )。
c. 执行 LeaveCriticalSection (WL )。
d. 返回 unused 。
2. 令 now 为标识当前时间的 时间值 (UTC)。
3. 令 currentRealm 为 当前 Realm Record 。
4. 执行 HostEnqueueTimeoutJob (timeoutJob ,
currentRealm , 𝔽 (waiterRecord 的 [[TimeoutTime]] ) - now )。
5. 返回 unused 。
25.4.3.16 AtomicCompareExchangeInSharedBlock ( block ,
byteIndexInBuffer , elementSize , expectedBytes ,
replacementBytes )
当调用时,抽象操作 AtomicCompareExchangeInSharedBlock 接受参数 block (一个 共享数据块 ),byteIndexInBuffer (一个
整数 ),elementSize (一个非负 整数 ),expectedBytes (一个 字节值列表 ),以及
replacementBytes (一个 字节值列表 ),并返回一个
字节值列表 。它执行以下步骤:
1. 令 execution 为 当前 agent 的
Agent
Record 中的 [[CandidateExecution]] 字段。
2. 令 eventsRecord 为 execution 中 [[EventsRecords]] 的 Agent Events Record ,其 [[AgentSignifier]] 是 AgentSignifier ()。
3. 令 rawBytesRead 为一个长度为 elementSize 的
列表 ,其元素为非确定性选择的
字节值 。
4. 注:在实现中,rawBytesRead
是底层硬件上加载链接、加载独占或读-修改-写指令的操作数的结果。非确定性是 内存模型 的语义规定,用于描述弱一致性硬件的可观察行为。
5. 注:预期值和读取值的比较在 读-修改-写修改函数
之外进行,以避免在预期值不等于读取值时不必要的强同步。
6. 如果 ByteListEqual (rawBytesRead ,
expectedBytes ) 为 true ,则:
a. 令 second 为一个新的 读-修改-写修改函数 ,其参数为
(oldBytes , newBytes ),捕获无内容,并在调用时原子性地执行以下步骤:
i. 返回 newBytes 。
b. 令 event 为 ReadModifyWriteSharedMemory
{ [[Order]] : seq-cst , [[NoTear]] : true , [[Block]] :
block , [[ByteIndex]] : byteIndexInBuffer , [[ElementSize]] : elementSize , [[Payload]] : replacementBytes , [[ModifyOp]] : second }。
7. 否则:
a. 令 event 为 ReadSharedMemory
{ [[Order]] : seq-cst , [[NoTear]] : true , [[Block]] :
block , [[ByteIndex]] : byteIndexInBuffer , [[ElementSize]] : elementSize }。
8. 将 event 追加到 eventsRecord 的 [[EventList]] 。
9. 将 Chosen Value Record {
[[Event]] : event , [[ChosenValue]] :
rawBytesRead } 追加到 execution 的 [[ChosenValues]]
。
10. 返回 rawBytesRead 。
25.4.3.17 AtomicReadModifyWrite ( typedArray , index ,
value , op )
抽象操作 AtomicReadModifyWrite 接受参数 typedArray (一个 ECMAScript
语言值 )、index (一个 ECMAScript
语言值 )、value (一个 ECMAScript
语言值 )和 op (一个 读-修改-写修改函数 ),并返回一个包含数字或 BigInt
的正常完成记录,或者抛出完成记录。op 接受两个 列表 的 字节值 作为参数,并返回一个 字节值列表 。该操作原子性地加载一个值,将其与另一个值组合,并存储组合的结果。它返回加载的值。当调用时,执行以下步骤:
1. 令 byteIndexInBuffer 为 ? ValidateAtomicAccessOnIntegerTypedArray (typedArray ,
index )。
2. 如果 typedArray 的 [[ContentType]] 是 bigint ,则令 v 为
? ToBigInt (value )。
3. 否则,令 v 为 𝔽 (? ToIntegerOrInfinity (value ))。
4. 执行 ? RevalidateAtomicAccess (typedArray ,
byteIndexInBuffer )。
5. 令 buffer 为 typedArray 的 [[ViewedArrayBuffer]] 。
6. 令 elementType 为 TypedArrayElementType (typedArray )。
7. 返回 GetModifySetValueInBuffer (buffer ,
byteIndexInBuffer , elementType , v , op )。
25.4.3.18 ByteListBitwiseOp ( op , xBytes ,
yBytes )
抽象操作 ByteListBitwiseOp 接受参数 op (&
、^
或
|
)、xBytes (一个 列表 的 字节值 ),以及 yBytes (一个 列表 的 字节值 )并返回一个 列表 的 字节值 。该操作原子性地对所有参数的 字节值 执行按位操作并返回一个 列表 的 字节值 。当调用时,执行以下步骤:
1. 断言 :xBytes 和 yBytes
具有相同数量的元素。
2. 令 result 为一个新的空 列表 。
3. 令 i 为 0。
4. 对于 xBytes 的每个元素 xByte ,执行以下操作:
a. 令 yByte 为 yBytes [i ]。
b. 如果 op 是 &
,则
i. 令 resultByte 为对 xByte 和
yByte 执行按位与操作的结果。
c. 否则,如果 op 是 ^
,则
i. 令 resultByte 为对 xByte 和
yByte 执行按位异或(XOR)操作的结果。
d. 否则,
i. 断言 :op 是 |
。
ii. 令 resultByte 为对 xByte 和
yByte 执行按位或操作的结果。
e. 将 i 设置为 i + 1。
f. 将 resultByte 添加到 result 。
5. 返回 result 。
25.4.3.19 ByteListEqual ( xBytes , yBytes )
抽象操作 ByteListEqual 接受参数 xBytes (一个 列表 的 字节值 )和 yBytes (一个 列表 的 字节值 )并返回一个布尔值。它在调用时执行以下步骤:
1. 如果 xBytes 和 yBytes 具有不同数量的元素,则返回
false 。
2. 令 i 为 0。
3. 对于 xBytes 的每个元素 xByte ,执行以下操作:
a. 令 yByte 为 yBytes [i ]。
b. 如果 xByte ≠ yByte ,返回
false 。
c. 将 i 设置为 i + 1。
4. 返回 true 。
25.4.4 Atomics.add ( typedArray , index , value
)
此函数在调用时执行以下步骤:
1. 令 type 为 TypedArrayElementType (typedArray )。
2. 令 isLittleEndian 为 surrounding agent
的 Agent
Record 的 [[LittleEndian]] 字段的值。
3. 令 add 为一个新的 读-修改-写修改函数 ,带有参数
(xBytes , yBytes ),捕获 type 和 isLittleEndian ,并在调用时执行以下步骤:
a. 令 x 为 RawBytesToNumeric (type ,
xBytes , isLittleEndian )。
b. 令 y 为 RawBytesToNumeric (type ,
yBytes , isLittleEndian )。
c. 如果 x 是 Number ,则
i. 令 sum 为 Number::add (x ,
y )。
d. 否则,
i. 断言 :x 是 BigInt 。
ii. 令 sum 为 BigInt::add (x ,
y )。
e. 令 sumBytes 为 NumericToRawBytes (type ,
sum , isLittleEndian )。
f. 断言 :sumBytes 、xBytes
和 yBytes 具有相同数量的元素。
g. 返回 sumBytes 。
4. 返回 ? AtomicReadModifyWrite (typedArray , index ,
value , add )。
25.4.5 Atomics.and ( typedArray , index , value
)
此函数在调用时执行以下步骤:
1. 令 and 为一个新的 读-修改-写修改函数 ,带有参数
(xBytes , yBytes ),不捕获任何内容,并在调用时原子性地执行以下步骤:
a. 返回 ByteListBitwiseOp (&
,
xBytes , yBytes )。
2. 返回 ? AtomicReadModifyWrite (typedArray , index ,
value , and )。
25.4.6 Atomics.compareExchange ( typedArray , index ,
expectedValue , replacementValue )
此函数在调用时执行以下步骤:
1. 令 byteIndexInBuffer 为 ? ValidateAtomicAccessOnIntegerTypedArray (typedArray ,
index )。
2. 令 buffer 为 typedArray .[[ViewedArrayBuffer]] 。
3. 令 block 为 buffer .[[ArrayBufferData]] 。
4. 如果 typedArray .[[ContentType]] 是
bigint ,则:
a. 令 expected 为 ? ToBigInt (expectedValue )。
b. 令 replacement 为 ? ToBigInt (replacementValue )。
5. 否则:
a. 令 expected 为 𝔽 (? ToIntegerOrInfinity (expectedValue ))。
b. 令 replacement 为 𝔽 (? ToIntegerOrInfinity (replacementValue ))。
6. 执行 ? RevalidateAtomicAccess (typedArray ,
byteIndexInBuffer )。
7. 令 elementType 为 TypedArrayElementType (typedArray )。
8. 令 elementSize 为 TypedArrayElementSize (typedArray )。
9. 令 isLittleEndian 为 surrounding agent
的 [[LittleEndian]] 字段的值。
10. 令 expectedBytes 为 NumericToRawBytes (elementType ,
expected , isLittleEndian )。
11. 令 replacementBytes 为 NumericToRawBytes (elementType ,
replacement , isLittleEndian )。
12. 如果 IsSharedArrayBuffer (buffer )
是 true ,则:
a. 令 rawBytesRead 为 AtomicCompareExchangeInSharedBlock (block ,
byteIndexInBuffer , elementSize , expectedBytes ,
replacementBytes )。
13. 否则:
a. 令 rawBytesRead 为一个 列表 ,长度为
elementSize ,其元素是从 block [byteIndexInBuffer ] 开始的
elementSize 字节序列。
b. 如果 ByteListEqual (rawBytesRead ,
expectedBytes ) 是 true ,则:
i. 将 replacementBytes 的各个字节存储到 block 中,从
block [byteIndexInBuffer ] 开始。
14. 返回 RawBytesToNumeric (elementType ,
rawBytesRead , isLittleEndian )。
25.4.7 Atomics.exchange ( typedArray , index ,
value )
此函数在调用时执行以下步骤:
1. 令 second 为一个新的 读-修改-写 修改函数 ,参数为
(oldBytes , newBytes ),不捕获任何内容,并在调用时执行以下步骤:
a. 返回 newBytes 。
2. 返回 ? AtomicReadModifyWrite (typedArray , index ,
value , second )。
25.4.8 Atomics.isLockFree ( size )
此函数在调用时执行以下步骤:
1. 令 n 为 ? ToIntegerOrInfinity (size )。
2. 令 AR 为 代理记录 。
3. 如果 n = 1,返回 AR .[[IsLockFree1]] 。
4. 如果 n = 2,返回 AR .[[IsLockFree2]] 。
5. 如果 n = 4,返回 true 。
6. 如果 n = 8,返回 AR .[[IsLockFree8]] 。
7. 返回 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 )
此函数在调用时执行以下步骤:
1. 令 byteIndexInBuffer 为 ? ValidateAtomicAccessOnIntegerTypedArray (typedArray ,
index )。
2. 执行 ? RevalidateAtomicAccess (typedArray ,
byteIndexInBuffer )。
3. 令 buffer 为 typedArray .[[ViewedArrayBuffer]] 。
4. 令 elementType 为 TypedArrayElementType (typedArray )。
5. 返回 GetValueFromBuffer (buffer ,
byteIndexInBuffer , elementType , true ,
seq-cst )。
25.4.10 Atomics.or ( typedArray , index , value
)
此函数在调用时执行以下步骤:
1. 令 or 为一个新的 读-修改-写
修改函数 ,参数为 (xBytes , yBytes ),该函数不捕获任何内容,并在调用时原子性地执行以下步骤:
a. 返回 ByteListBitwiseOp (|
,
xBytes , yBytes )。
2. 返回 ? AtomicReadModifyWrite (typedArray , index ,
value , or )。
25.4.11 Atomics.store ( typedArray , index ,
value )
此函数在调用时执行以下步骤:
1. 令 byteIndexInBuffer 为 ? ValidateAtomicAccessOnIntegerTypedArray (typedArray ,
index )。
2. 如果 typedArray .[[ContentType]] 是
bigint ,则令 v 为 ? ToBigInt (value )。
3. 否则,令 v 为 𝔽 (? ToIntegerOrInfinity (value ))。
4. 执行 ? RevalidateAtomicAccess (typedArray ,
byteIndexInBuffer )。
5. 令 buffer 为 typedArray .[[ViewedArrayBuffer]] 。
6. 令 elementType 为 TypedArrayElementType (typedArray )。
7. 执行 SetValueInBuffer (buffer ,
byteIndexInBuffer , elementType , v , true ,
seq-cst )。
8. 返回 v 。
25.4.12 Atomics.sub ( typedArray , index ,
value )
此函数在调用时执行以下步骤:
1. 令 type 为 TypedArrayElementType (typedArray )。
2. 令 isLittleEndian 为 surrounding agent
的 [[LittleEndian]] 字段的值。
3. 令 subtract 为一个新的 读-修改-写 修改函数 ,参数为
(xBytes , yBytes ),该函数捕获 type 和
isLittleEndian ,并在调用时原子性地执行以下步骤:
a. 令 x 为 RawBytesToNumeric (type ,
xBytes , isLittleEndian )。
b. 令 y 为 RawBytesToNumeric (type ,
yBytes , isLittleEndian )。
c. 如果 x 是一个
Number ,则
i. 令 difference 为 Number::subtract (x ,
y )。
d. 否则,
i. 断言 : x 是一个
BigInt 。
ii. 令 difference 为 BigInt::subtract (x ,
y )。
e. 令 differenceBytes 为 NumericToRawBytes (type ,
difference , isLittleEndian )。
f. 断言 :
differenceBytes 、xBytes 和 yBytes 具有相同数量的元素。
g. 返回 differenceBytes 。
4. 返回 ? AtomicReadModifyWrite (typedArray , index ,
value , subtract )。
25.4.13 Atomics.wait ( typedArray , index ,
value , timeout )
此函数将 surrounding agent
放入等待队列,并使其暂停,直到被通知或等待超时,返回一个区分这些情况的字符串。
它在调用时执行以下步骤:
1. 返回 ? DoWait (sync , typedArray ,
index , value , timeout )。
25.4.14 Atomics.waitAsync ( typedArray , index ,
value , timeout )
此函数返回一个 Promise,当调用的 agent 被通知或超时时,该 Promise 被解析。
它在调用时执行以下步骤:
1. 返回 ? DoWait (async , typedArray ,
index , value , timeout )。
25.4.15 Atomics.notify ( typedArray , index ,
count )
此函数通知在等待队列中睡眠的一些 agent 。
它在调用时执行以下步骤:
1. 令 byteIndexInBuffer 为 ? ValidateAtomicAccessOnIntegerTypedArray (typedArray ,
index , true )。
2. 如果 count 是 undefined ,则
a. 令 c 为 +∞。
3. 否则,
a. 令 intCount 为 ? ToIntegerOrInfinity (count )。
b. 令 c 为 max (intCount , 0)。
4. 令 buffer 为 typedArray .[[ViewedArrayBuffer]] 。
5. 令 block 为 buffer .[[ArrayBufferData]] 。
6. 如果 IsSharedArrayBuffer (buffer )
是 false ,返回 +0 𝔽 。
7. 令 WL 为 GetWaiterList (block ,
byteIndexInBuffer )。
8. 执行 EnterCriticalSection (WL )。
9. 令 S 为 RemoveWaiters (WL ,
c )。
10. 对于 S 的每个元素 W ,执行
a. 执行 NotifyWaiter (WL ,
W )。
11. 执行 LeaveCriticalSection (WL )。
12. 令 n 为 S 中的元素数量。
13. 返回 𝔽 (n )。
25.4.16 Atomics.xor ( typedArray , index ,
value )
此函数在调用时执行以下步骤:
1. 令 xor 为一个新的 读-改-写修改函数 ,其参数为
(xBytes , yBytes ),不捕获任何内容,并在调用时执行以下步骤,以原子方式完成:
a. 返回 ByteListBitwiseOp (^
,
xBytes , yBytes )。
2. 返回 ? AtomicReadModifyWrite (typedArray , index ,
value , xor )。
25.4.17 Atomics [ @@toStringTag ]
@@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 ,则从结果中删除该属性。
1. 让 jsonString 成为 ? ToString (text )。
2. 按照 ECMA-404 的规定,将 StringToCodePoints (jsonString )
作为 JSON 文本进行解析。如果它不是该规范中定义的有效 JSON 文本,则抛出 SyntaxError 异常。
3. 让 scriptString 成为 字符串连接
"(" 、jsonString 和 ");" 的结果。
4. 让 script 成为 ParseText (StringToCodePoints (scriptString ),脚本 )。
5. 注意:提前错误 规则在 13.2.5.1
中对上述 ParseText 调用有特殊处理。
6. 断言 :script 是一个 语法节点 。
7. 让 completion 成为 完成 (评估 的
script )。
8. 注意:属性定义评估
语义在 13.2.5.5
中对上述评估有特殊处理。
9. 让 unfiltered 成为 completion .[[Value]] 。
10. 断言 :unfiltered
是字符串、数字、布尔值、数组字面量 或 对象字面量 定义的对象,或
null 。
11. 如果 IsCallable (reviver ) 为
true ,则
a. 让 root 成为 OrdinaryObjectCreate (%Object.prototype% )。
b. 让 rootName 成为空字符串。
c. 执行 ! CreateDataPropertyOrThrow (root ,rootName ,unfiltered )。
d. 返回 ? InternalizeJSONProperty (root ,rootName ,reviver )。
12. 否则,
a. 返回 unfiltered 。
该函数的 "length" 属性为 2 𝔽 。
注
有效的 JSON 文本是 ECMAScript 主要表达式 语法的子集。步骤 2 验证 jsonString
是否符合该子集,步骤 10 断言解析和评估返回的值是否为适当类型。
然而,由于 13.2.5.5
在 JSON.parse
期间表现不同,相同的源文本在作为 主要表达式
进行评估时可能产生不同的结果。此外,对对象字面量中重复 "__proto__" 属性的提前错误也不适用于
JSON.parse
,这意味着并非所有被 JSON.parse
接受的文本都有效为 主要表达式 ,尽管符合语法。
25.5.1.1 InternalizeJSONProperty (
holder ,name ,reviver )
抽象操作 InternalizeJSONProperty 接受参数 holder (对象),name (字符串),和
reviver (函数对象 ),返回一个 正常完成包含 的
ECMAScript 语言值 或一个
抛出完成 。
注 1
如果 [[Delete]] 或 CreateDataProperty 返回
false ,则该算法有意不抛出异常。
当调用时,它执行以下步骤:
1. 让 val 成为 ? Get (holder ,name )。
2. 如果 val 是一个对象 ,则
a. 让 isArray 成为 ? IsArray (val )。
b. 如果 isArray 为 true ,则
i. 让 len 成为 ? LengthOfArrayLike (val )。
ii. 让 I 为 0。
iii. 重复,直到 I < len ,
1. 让 prop 成为 ! ToString (𝔽 (I ))。
2. 让 newElement 成为 ? InternalizeJSONProperty (val ,prop ,reviver )。
3. 如果 newElement 为
undefined ,则
a. 执行 ? val .[[Delete]] (prop )。
4. 否则,
a. 执行 ? CreateDataProperty (val ,prop ,newElement )。
5. 将 I 设为 I + 1。
c. 否则,
i. 让 keys 成为 ? EnumerableOwnProperties
(val ,key )。
ii. 对于 keys 中的每个字符串 P ,
1. 让 newElement 成为 ? InternalizeJSONProperty (val ,P ,reviver )。
2. 如果 newElement 为
undefined ,则
a. 执行 ? val .[[Delete]] (P )。
3. 否则,
a. 执行 ? CreateDataProperty (val ,P ,newElement )。
3. 返回 ? Call (reviver ,holder ,«
name ,val »)。
对于符合标准的 JSON.parse
实现,不允许扩展 JSON 语法。如果某个实现希望支持修改或扩展的 JSON 交换格式,必须通过定义不同的解析函数来实现。
注 2
如果对象中存在重复的名称字符串,词法上前面的值将被覆盖。
25.5.2 JSON.stringify ( value [ , replacer [ ,
space ] ] )
该函数返回一个 UTF-16 编码的 JSON 格式字符串,表示一个 ECMAScript 语言值 ,或者
undefined 。它可以接受三个参数。value 参数是一个 ECMAScript
语言值 ,通常是一个对象或数组,但也可以是字符串、布尔值、数字或 null 。可选的 replacer
参数可以是一个函数,用于改变对象和数组的字符串化方式,或者是一个字符串和数字数组,作为选择要字符串化的对象属性的包含列表。可选的 space 参数 是一个字符串 或数字,允许在结果中注入空白以提高人类可读性。
调用时,它执行以下步骤:
1. 让 stack 成为一个新的空 列表 。
2. 让 indent 成为空字符串。
3. 让 PropertyList 成为 undefined 。
4. 让 ReplacerFunction 成为 undefined 。
5. 如果 replacer 是一个对象 ,则
a. 如果 IsCallable (replacer ) 为
true ,则
i. 将 ReplacerFunction 设为 replacer 。
b. 否则,
i. 让 isArray 成为 ? IsArray (replacer )。
ii. 如果 isArray 为 true ,则
1. 将 PropertyList 设为一个新的空 列表 。
2. 让 len 成为 ? LengthOfArrayLike (replacer )。
3. 让 k 为 0。
4. 重复,当 k < len 时,
a. 让 prop 成为 ! ToString (𝔽 (k ))。
b. 让 v 成为 ? Get (replacer , prop )。
c. 让 item 成为 undefined 。
d. 如果 v 是一个字符串 ,则
i. 将 item 设为 v 。
e. 否则如果 v 是一个数字 ,则
i. 将 item 设为 ! ToString (v )。
f. 否则如果 v 是一个对象 ,则
i. 如果 v 有一个 [[StringData]] 或 [[NumberData]] 内部槽,设
item 为 ? ToString (v )。
g. 如果 item 不是 undefined
并且 PropertyList 不包含 item ,则
i. 将 item 添加到 PropertyList 。
h. 将 k 设为 k + 1。
6. 如果 space 是一个对象 ,则
a. 如果 space 有一个 [[NumberData]]
内部槽,则
i. 将 space 设为 ? ToNumber (space )。
b. 否则如果 space 有一个 [[StringData]] 内部槽,则
i. 将 space 设为 ? ToString (space )。
7. 如果 space 是一个数字 ,则
a. 让 spaceMV 成为 ! ToIntegerOrInfinity (space )。
b. 将 spaceMV 设为 min (10,spaceMV )。
c. 如果 spaceMV < 1,让 gap 成为空字符串;否则,让
gap 为包含 spaceMV 次代码单元 0x0020 (空格) 的字符串值。
8. 否则如果 space 是一个字符串 ,则
a. 如果 space 的长度 ≤ 10,让 gap 成为
space ;否则让 gap 成为 子字符串 从 0 到 10 的 space 。
9. 否则,
a. 让 gap 成为空字符串。
10. 让 wrapper 成为 OrdinaryObjectCreate (%Object.prototype% )。
11. 执行 ! CreateDataPropertyOrThrow (wrapper ,
空字符串, value )。
12. 让 state 成为 JSON 序列化记录 { [[ReplacerFunction]] : ReplacerFunction , [[Stack]] : stack , [[Indent]] :
indent , [[Gap]] : gap , [[PropertyList]] : PropertyList }。
13. 返回 ? SerializeJSONProperty (state , 空字符串,
wrapper )。
该函数的 "length" 属性为 3 𝔽 。
注 1
JSON 结构允许嵌套到任意深度,但必须是非循环的。如果 value 是或包含循环结构,则该函数必须抛出 TypeError
异常。这是一个无法字符串化的值的示例:
a = [];
a[0 ] = a;
my_text = JSON .stringify (a);
注 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 序列化记录 是一个
记录
值,用于启用 JSON 格式的序列化。
JSON 序列化记录具有在 表 75 中列出的字段。
表 75: JSON 序列化记录 字段
字段名
值
含义
[[ReplacerFunction]]
一个 函数对象 或
undefined
一个可以为对象属性提供替代值的函数(来自 JSON.stringify 的
replacer 参数)。
[[PropertyList]]
一个 字符串列表
或 undefined
在序列化非数组对象时包含的属性名称(来自 JSON.stringify 的
replacer 参数)。
[[Gap]]
一个字符串
缩进单位(来自 JSON.stringify 的 space 参数)。
[[Stack]]
一个 对象列表
正在被序列化的嵌套对象集。用于检测循环结构。
[[Indent]]
一个字符串
当前的缩进。
25.5.2.2 SerializeJSONProperty ( state , key ,
holder )
抽象操作 SerializeJSONProperty 接受参数 state (一个 JSON
序列化记录 )、key (一个字符串)和 holder (一个对象),并返回
一个 正常完成 ,
该完成包含一个字符串或 undefined ,或者一个 抛出完成 。它在调用时执行以下步骤:
1. 让 value 为 ? Get (holder , key ).
2. 如果 value 是一个对象
或 value 是一个
BigInt ,那么
a. 让 toJSON 为 ? GetV (value , "toJSON" ).
b. 如果 IsCallable (toJSON )
为 true ,那么
i. 将 value 设置为 ? Call (toJSON , value , «
key »).
3. 如果 state .[[ReplacerFunction]]
不为 undefined ,那么
a. 将 value 设置为 ? Call (state .[[ReplacerFunction]] , holder , « key ,
value »).
4. 如果 value 是一个对象 ,
那么
a. 如果 value 有一个 [[NumberData]] 内部槽,则
i. 将 value 设置为 ? ToNumber (value ).
b. 否则,如果 value 有一个 [[StringData]] 内部槽,则
i. 将 value 设置为 ? ToString (value ).
c. 否则,如果 value 有一个 [[BooleanData]] 内部槽,则
i. 将 value 设置为 value .[[BooleanData]] .
d. 否则,如果 value 有一个 [[BigIntData]] 内部槽,则
i. 将 value 设置为 value .[[BigIntData]] .
5. 如果 value 为 null ,返回
"null" 。
6. 如果 value 为 true ,返回
"true" 。
7. 如果 value 为 false ,返回
"false" 。
8. 如果 value 是一个字符串 ,返回
QuoteJSONString (value ).
9. 如果 value 是一个数字 ,那么
a. 如果 value 是 有限 ,返回
! ToString (value ).
b. 返回 "null" 。
10. 如果 value 是一个
BigInt ,抛出一个 TypeError 异常。
11. 如果 value 是一个对象
且 IsCallable (value ) 为
false ,那么
a. 让 isArray 为 ? IsArray (value ).
b. 如果 isArray 为 true ,返回
? SerializeJSONArray (state , value ).
c. 返回 ? SerializeJSONObject (state ,
value ).
12. 返回 undefined 。
25.5.2.3 QuoteJSONString ( value )
抽象操作 QuoteJSONString 接受一个参数 value (一个字符串),并返回一个字符串。它将 value 包裹在
0x0022(引号)代码单元中,并对其中的某些其他代码单元进行转义。该操作将 value 解释为 UTF-16 编码的代码点序列,如 6.1.4
中所述。它在调用时执行以下步骤:
1. 让 product 为仅包含代码单元 0x0022(引号)的字符串值。
2. 对于每个 C 在 StringToCodePoints (value )
中,执行
a. 如果 C 在 表 76 的
“代码点” 列中列出,那么
i. 将 product 设置为 字符串连接
的 product 和 C 的转义序列,如相应行的 “转义序列” 列所指定。
b. 否则,如果 C 的数值小于 0x0020(空格)或 C 的数值与
前导代理项 或 后续代理项 相同,那么
i. 让 unit 为数值与 C 相同的代码单元。
ii. 将 product 设置为 字符串连接
的 product 和 UnicodeEscape (unit )。
c. 否则,
i. 将 product 设置为 字符串连接
的 product 和 UTF16EncodeCodePoint (C )。
3. 将 product 设置为 字符串连接 的
product 和代码单元 0x0022(引号)。
4. 返回 product 。
表 76:JSON 单字符转义序列
代码点
Unicode 字符名称
转义序列
U+0008
退格
\b
U+0009
制表符
\t
U+000A
换行 (LF)
\n
U+000C
换页 (FF)
\f
U+000D
回车 (CR)
\r
U+0022
引号
\"
U+005C
反斜杠
\\
25.5.2.4 UnicodeEscape ( C )
抽象操作 UnicodeEscape 接受一个参数 C (一个代码单元),并返回一个字符串。它将 C 表示为一个 Unicode 转义序列。它在调用时执行以下步骤:
1. 让 n 为 C 的数值。
2. 断言 : n ≤ 0xFFFF。
3. 让 hex 为 n 的字符串表示,格式为小写十六进制数。
4. 返回代码单元 0x005C(反斜杠)、"u" 和 StringPad (hex , 4,
"0" , start ) 的 字符串连接 。
25.5.2.5 SerializeJSONObject ( state , value )
抽象操作 SerializeJSONObject 接受两个参数 state (一个 JSON
序列化记录 )和 value (一个对象),并返回一个字符串或一个 抛出完成记录 。它对一个对象进行序列化。调用时执行以下步骤:
1. 如果 state .[[Stack]] 包含
value ,抛出一个 TypeError 异常,因为结构是循环的。
2. 将 value 添加到 state .[[Stack]] 中。
3. 让 stepback 为 state .[[Indent]] 。
4. 将 state .[[Indent]] 设置为
字符串连接 state .[[Indent]] 和 state .[[Gap]] 的结果。
5. 如果 state .[[PropertyList]] 不为
undefined ,则
a. 让 K 为 state .[[PropertyList]] 。
6. 否则,
a. 让 K 为 ? EnumerableOwnProperties (value ,
key )。
7. 让 partial 为一个新的空 列表 。
8. 对于 K 的每个元素 P ,执行
a. 让 strP 为 ? SerializeJSONProperty (state , P ,
value )。
b. 如果 strP 不为 undefined ,则
i. 让 member 为 QuoteJSONString (P )。
ii. 将 member 设置为 字符串连接
member 和 ":" 的结果。
iii. 如果 state .[[Gap]]
不是空字符串,则
1. 将 member 设置为 字符串连接
member 和代码单元 0x0020(空格)的结果。
iv. 将 member 设置为 字符串连接
member 和 strP 的结果。
v. 将 member 添加到 partial 中。
9. 如果 partial 为空,则
a. 让 final 为 "{}" 。
10. 否则,
a. 如果 state .[[Gap]] 是空字符串,则
i. 让 properties 为通过用代码单元 0x002C(逗号)分隔的
partial 中所有元素字符串拼接而成的字符串值。逗号既不会插入到第一个字符串之前,也不会插入到最后一个字符串之后。
ii. 让 final 为 字符串连接
"{" 、properties 和 "}" 的结果。
b. 否则,
i. 让 separator 为代码单元 0x002C(逗号)、代码单元 0x000A(换行符)和
state .[[Indent]] 的 字符串连接 。
ii. 让 properties 为通过用 separator 分隔的
partial 中所有元素字符串拼接而成的
字符串值。separator 字符串既不会插入到第一个字符串之前,也不会插入到最后一个字符串之后。
iii. 让 final 为 字符串连接
"{" 、代码单元 0x000A(换行符)、state .[[Indent]] 、properties 、代码单元 0x000A(换行符)stepback 和
"}" 的结果。
11. 移除 state .[[Stack]] 中的最后一个元素。
12. 将 state .[[Indent]] 设置为
stepback 。
13. 返回 final 。
25.5.2.6 SerializeJSONArray ( state , value )
抽象操作 SerializeJSONArray 接受两个参数 state (一个 JSON
序列化记录 )和 value (一个 ECMAScript
语言值 ),并返回一个字符串或一个 正常完成记录 。它对一个数组进行序列化。调用时执行以下步骤:
1. 如果 state .[[Stack]] 包含
value ,抛出一个 TypeError 异常,因为结构是循环的。
2. 将 value 添加到 state .[[Stack]] 中。
3. 让 stepback 为 state .[[Indent]] 。
4. 将 state .[[Indent]] 设置为
字符串连接 state .[[Indent]] 和 state .[[Gap]] 的结果。
5. 让 partial 为一个新的空 列表 。
6. 让 len 为 ? LengthOfArrayLike (value )。
7. 让 index 为 0。
8. 重复以下步骤,直到 index < len :
a. 让 strP 为 ? SerializeJSONProperty (state ,
! ToString (𝔽 (index )),
value )。
b. 如果 strP 是 undefined ,则
i. 将 "null" 添加到 partial 中。
c. 否则,
i. 将 strP 添加到 partial 中。
d. 将 index 设置为 index + 1。
9. 如果 partial 为空,则
a. 让 final 为 "[]" 。
10. 否则,
a. 如果 state .[[Gap]] 是空字符串,则
i. 让 properties 为通过用代码单元 0x002C(逗号)分隔的
partial 中所有元素字符串拼接而成的字符串值。逗号既不会插入到第一个字符串之前,也不会插入到最后一个字符串之后。
ii. 让 final 为 字符串连接
"[" 、properties 和 "]" 的结果。
b. 否则,
i. 让 separator 为代码单元 0x002C(逗号)、代码单元 0x000A(换行符)和
state .[[Indent]] 的 字符串连接 。
ii. 让 properties 为通过用 separator 分隔的
partial 中所有元素字符串拼接而成的字符串值。separator 字符串既不会插入到第一个字符串之前,也不会插入到最后一个字符串之后。
iii. 让 final 为 字符串连接
"[" 、代码单元 0x000A(换行符)、state .[[Indent]] 、properties 、代码单元 0x000A(换行符)stepback 和
"]" 的结果。
11. 移除 state .[[Stack]] 中的最后一个元素。
12. 将 state .[[Indent]] 设置为
stepback 。
13. 返回 final 。
注
数组的表示仅包括从 区间
+0 𝔽 (包含)到 array.length
(不包含)的元素。键不是 数组索引
的属性被排除在字符串化之外。数组被字符串化为一个左方括号,元素用逗号分隔,然后是一个右方括号。
25.5.3 JSON [ @@toStringTag ]
@@toStringTag 属性的初始值为字符串
"JSON" 。
该属性的特性为 { [[Writable]] : false ,
[[Enumerable]] : false , [[Configurable]] : true }。
26 内存管理
26.1 WeakRef 对象
A WeakRef
是一个对象,用于引用目标对象或符号,而不阻止其被垃圾回收。WeakRefs
可以被解除引用,以允许访问目标值,前提是目标尚未被垃圾回收。
26.1.1 WeakRef 构造函数
WeakRef 构造函数 :
是 %WeakRef% 。
是 "WeakRef" 属性的初始值,属于 全局对象 。
作为 构造函数 被调用时,会创建并初始化一个新的
WeakRef。
不应作为函数调用,若以此方式调用会抛出异常。
可以用作类定义中的 extends
子句的值。旨在继承指定的 WeakRef
行为的子类 构造函数 必须包含一个
super
调用到 WeakRef
构造函数 ,以使用必要的内部状态创建并初始化子类实例,以支持
WeakRef.prototype
内置方法。
26.1.1.1 WeakRef ( target )
此函数在调用时执行以下步骤:
1. 如果 NewTarget 为 undefined ,抛出
TypeError 异常。
2. 如果 CanBeHeldWeakly (target )
为 false ,抛出 TypeError 异常。
3. 让 weakRef 为 ? OrdinaryCreateFromConstructor (NewTarget,
"%WeakRef.prototype%" , « [[WeakRefTarget]] »)。
4. 执行 AddToKeptObjects (target )。
5. 将 weakRef .[[WeakRefTarget]]
设置为 target 。
6. 返回 weakRef 。
26.1.2 WeakRef 构造函数的属性
WeakRef 构造函数 :
26.1.2.1 WeakRef.prototype
WeakRef.prototype
的初始值是 WeakRef
原型 对象。
该属性的属性描述符为 { [[Writable]] : false ,
[[Enumerable]] : false , [[Configurable]] : false }。
26.1.3 WeakRef 原型对象的属性
WeakRef 原型 对象:
26.1.3.1 WeakRef.prototype.constructor
WeakRef.prototype.constructor
的初始值是 %WeakRef% 。
该属性的属性描述符为 { [[Writable]] : false ,
[[Enumerable]] : false , [[Configurable]] : true }。
26.1.3.2 WeakRef.prototype.deref ( )
调用此方法时执行以下步骤:
1. 将 weakRef 设为 this 值。
2. 执行 ? RequireInternalSlot (weakRef ,
[[WeakRefTarget]] )。
3. 返回 WeakRefDeref (weakRef )。
注
如果 WeakRef 返回一个
不为 undefined 的 target 值,则该 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 [ @@toStringTag ]
@@toStringTag 属性的初始值是
字符串值 "WeakRef" 。
此属性具有以下特性 { [[Writable]] : false ,
[[Enumerable]] : false , [[Configurable]] :
true }。
26.1.4 WeakRef 抽象操作
26.1.4.1 WeakRefDeref ( weakRef )
抽象操作 WeakRefDeref 接受参数 weakRef (一个 WeakRef ),并返回一个 ECMAScript
语言值 。它在调用时执行以下步骤:
1. 让 target 作为 weakRef .[[WeakRefTarget]] 。
2. 如果 target 不是 empty ,
则
a. 执行 AddToKeptObjects (target )。
b. 返回 target 。
3. 返回 undefined 。
注
此抽象操作与 WeakRef.prototype.deref 的定义是分开的,主要是为了便于简洁地定义存活性。
26.1.5 WeakRef 实例的属性
WeakRef 实例是
普通对象 ,从 WeakRef
原型 继承属性。WeakRef 实例还具有
一个 [[WeakRefTarget]] 内部槽。
26.2 FinalizationRegistry 对象
FinalizationRegistry
是一种管理目标对象和符号被垃圾回收时执行的清理操作的注册和注销的对象。
26.2.1 FinalizationRegistry 构造函数
FinalizationRegistry 构造函数 :
是 %FinalizationRegistry% 。
是 "FinalizationRegistry" 属性的初始值,该属性属于 global
object 。
当作为 构造函数 调用时,会创建并初始化一个新的 FinalizationRegistry。
不应作为函数调用,如果以这种方式调用会抛出异常。
可用作类定义的 extends
子句中的值。旨在继承指定 FinalizationRegistry
行为的子类 构造函数 必须包含一个
super
调用到 FinalizationRegistry
构造函数
以创建和初始化子类实例,并具备支持 FinalizationRegistry.prototype
内置方法所需的内部状态。
26.2.1.1 FinalizationRegistry ( cleanupCallback )
当调用此函数时,执行以下步骤:
1. 如果 NewTarget 是 undefined ,则抛出
TypeError 异常。
2. 如果 IsCallable (cleanupCallback )
为 false ,则抛出 TypeError 异常。
3. 让 finalizationRegistry 为 ? OrdinaryCreateFromConstructor (NewTarget,
"%FinalizationRegistry.prototype%" , « [[Realm]] , [[CleanupCallback]] , [[Cells]] »)。
4. 让 fn 为当前活跃的函数对象。
5. 将 finalizationRegistry .[[Realm]] 设置为 fn .[[Realm]] 。
6. 将 finalizationRegistry .[[CleanupCallback]] 设置为 HostMakeJobCallback (cleanupCallback )。
7. 将 finalizationRegistry .[[Cells]] 设置为一个新的空 List 。
8. 返回 finalizationRegistry 。
26.2.2 FinalizationRegistry 构造函数的属性
FinalizationRegistry
构造函数 :
26.2.2.1 FinalizationRegistry.prototype
FinalizationRegistry.prototype
的初始值为 FinalizationRegistry
prototype 对象。
该属性具有以下特性:{ [[Writable]] : false ,
[[Enumerable]] : false , [[Configurable]] :
false }。
26.2.3 FinalizationRegistry 原型对象的属性
FinalizationRegistry 原型 对象:
是 %FinalizationRegistry.prototype% 。
拥有一个 [[Prototype]] 内部插槽,其值为 %Object.prototype% 。
是一个 普通对象 。
不具有 [[Cells]] 和 [[CleanupCallback]]
内部插槽。
26.2.3.1 FinalizationRegistry.prototype.constructor
FinalizationRegistry.prototype.constructor
的初始值是 %FinalizationRegistry% 。
26.2.3.2 FinalizationRegistry.prototype.register ( target ,
heldValue [ , unregisterToken ] )
该方法在调用时执行以下步骤:
1. 让 finalizationRegistry 成为
this 值。
2. 执行 ? RequireInternalSlot (finalizationRegistry ,
[[Cells]] ).
3. 如果 CanBeHeldWeakly (target )
是 false ,则抛出 TypeError 异常。
4. 如果 SameValue (target ,
heldValue ) 是 true ,则抛出 TypeError 异常。
5. 如果 CanBeHeldWeakly (unregisterToken )
是 false ,则
a. 如果 unregisterToken 不是
undefined ,则抛出 TypeError 异常。
b. 将 unregisterToken 设置为
empty 。
6. 让 cell 成为 Record
{ [[WeakRefTarget]] : target , [[HeldValue]] : heldValue , [[UnregisterToken]] : unregisterToken }。
7. 将 cell 添加到
finalizationRegistry .[[Cells]] 中。
8. 返回 undefined 。
注
根据本规范中的算法和定义,cell .[[HeldValue]] 在
finalizationRegistry .[[Cells]] 中包含 cell 时是 活跃的 ;但是,这并不一定意味着 cell .[[UnregisterToken]]
或 cell .[[Target]] 是 活跃的 。例如,将一个对象注册为其自身的注销令牌不会使对象永远保持活跃状态。
26.2.3.3 FinalizationRegistry.prototype.unregister (
unregisterToken )
该方法在调用时执行以下步骤:
1. 让 finalizationRegistry 成为
this 值。
2. 执行 ? RequireInternalSlot (finalizationRegistry ,
[[Cells]] ).
3. 如果 CanBeHeldWeakly (unregisterToken )
是 false ,则抛出 TypeError 异常。
4. 让 removed 为 false 。
5. 对于每个 Record
{ [[WeakRefTarget]] , [[HeldValue]] , [[UnregisterToken]] } cell 在
finalizationRegistry .[[Cells]] 中,执行
a. 如果 cell .[[UnregisterToken]] 不是 empty 并且 SameValue (cell .[[UnregisterToken]] , unregisterToken ) 是
true ,则
i. 从 finalizationRegistry .[[Cells]] 中移除 cell 。
ii. 将 removed 设置为 true 。
6. 返回 removed 。
26.2.3.4 FinalizationRegistry.prototype [ @@toStringTag ]
@@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 Iterable 接口
Iterable 接口包括在表
77 中描述的属性:
表 77: Iterable 接口必需的属性
属性
值
要求
@@iterator
返回一个 Iterator 对象的函数
返回的对象必须符合 Iterator 接口。
27.1.1.2 Iterator 接口
实现了 Iterator 接口的对象必须包含在表
78 中列出的属性。这些对象也可以实现表
79 中的属性。
表 78: Iterator 接口必需的属性
属性
值
要求
"next"
返回一个 IteratorResult 对象的函数
返回的对象必须符合 IteratorResult 接口。如果对 Iterator 的 next
方法的先前调用返回了一个其
"done" 属性为 true 的 IteratorResult 对象,则该对象的所有后续
next
方法调用也应该返回一个其 "done" 属性为 true 的
IteratorResult 对象。然而,这一要求并不强制执行。
注 1
可以将参数传递给 next
函数,但它们的解释和有效性取决于目标 Iterator 。for-of
语句和其他常见的
Iterator 用户不会传递任何参数,因此预期用于这种方式的 Iterator 对象必须能够处理无参数调用。
表 79: Iterator 接口可选的属性
属性
值
要求
"return"
返回一个 IteratorResult 对象的函数
返回的对象必须符合 IteratorResult 接口。调用此方法会通知 Iterator 对象调用者不打算再对 Iterator 进行更多的
next
方法调用。返回的 IteratorResult 对象通常会有一个 "done" 属性,其值为
true ,以及一个 "value" 属性,其值为传递给 return
方法的参数。然而,这一要求并不强制执行。
"throw"
返回一个 IteratorResult 对象的函数
返回的对象必须符合 IteratorResult 接口。调用此方法会通知 Iterator
对象调用者检测到了一个错误条件。参数可以用于识别错误条件,通常是一个异常对象。典型的响应是 throw
传递的参数值。如果方法不
throw
,返回的 IteratorResult 对象通常会有一个 "done" 属性,其值为
true 。
注 2
通常,调用这些方法的调用者应在调用之前检查其存在性。包括 for
-of
、yield*
和数组解构在内的某些
ECMAScript 语言特性会在执行存在性检查后调用这些方法。大多数接受 Iterable 对象作为参数的 ECMAScript 库函数也会有条件地调用这些方法。
27.1.1.3 AsyncIterable 接口
AsyncIterable 接口包括在表 80 中描述的属性:
表 80: AsyncIterable 接口必需的属性
属性
值
要求
@@asyncIterator
返回一个 AsyncIterator 对象的函数
返回的对象必须符合 AsyncIterator 接口。
27.1.1.4 AsyncIterator 接口
实现 AsyncIterator 接口的对象必须包括表
81 中的属性。这些对象还可以实现表 82 中的属性。
表 81: AsyncIterator 接口必需的属性
属性
值
要求
"next"
返回一个 IteratorResult 对象的 promise
返回的 promise 被兑现时,必须兑现为一个符合 IteratorResult 接口的对象。如果对一个
AsyncIterator 的 next
方法的先前调用返回了一个 IteratorResult 对象的 promise
且其 "done" 属性为 true ,那么对该对象的所有后续
next
方法调用也应该返回一个 IteratorResult 对象的 promise,其 "done"
属性为 true 。但这一要求并不强制执行。
此外,作为兑现值的 IteratorResult 对象应具有一个 "value" 属性,其值
不是 promise(或 "thenable")。但这一要求也不强制执行。
Note 1
可以将参数传递给 next
函数,但其解释和有效性取决于目标 AsyncIterator 。
for
-await
-of
语句和其他常见的 AsyncIterators 使用者不传递任何
参数,因此期望以这种方式使用的 AsyncIterator 对象必须能够处理无参数调用。
表 82: AsyncIterator 接口可选的属性
属性
值
要求
"return"
返回一个 IteratorResult 对象的 promise
返回的 promise 被兑现时,必须兑现为一个符合 IteratorResult 接口的对象。调用此方法
通知 AsyncIterator 对象调用者不打算再对该 AsyncIterator 进行更多的 next
方法调用。返回的 promise 将兑现为一个 IteratorResult 对象,该对象通常具有一个
"done" 属性,其值为 true ,以及一个 "value"
属性,其值为传递给 return
方法的参数。然而,这一要求并不强制执行。
此外,作为兑现值的 IteratorResult 对象应具有一个 "value" 属性,其值
不是 promise(或 "thenable")。如果参数值以典型方式使用,如果它是被拒绝的 promise,
则应返回一个因相同原因被拒绝的 promise;如果它是被兑现的 promise,则其兑现值应作为
返回 promise 的 IteratorResult 对象的 "value" 属性。然而,这些要求
也不强制执行。
"throw"
返回一个 IteratorResult 对象的 promise
返回的 promise 被兑现时,必须兑现为一个符合 IteratorResult 接口的对象。调用此方法
通知 AsyncIterator 对象调用者已经检测到错误条件。参数可以用于标识错误条件,通常将是
一个异常对象。典型的响应是返回一个被拒绝的 promise,该 promise 被拒绝的原因是传递的参数。
如果返回的 promise 被兑现,IteratorResult 的兑现值通常具有一个 "done"
属性,其值为 true 。此外,它还应具有一个 "value" 属性,其值
不是 promise(或 "thenable"),但这一要求并不强制执行。
Note 2
通常,调用这些方法的调用者应该在调用之前检查它们的存在。某些 ECMAScript 语言特性,包括
for
-await
-of
和 yield*
,在进行存在性检查后调用
这些方法。
27.1.1.5 IteratorResult 接口
IteratorResult 接口包括 表 83 中列出的属性:
表 83: IteratorResult 接口属性
属性
值
要求
"done"
布尔值
这是 iterator next
方法调用的结果状态。如果迭代器已到达末尾,"done" 为
true 。如果未到达末尾,"done" 为 false
并且有可用的值。如果不存在 "done" 属性(无论是自身的还是继承的),则视为 false 。
"value"
一个 ECMAScript 语言值
如果 "done" 为 false ,这是当前迭代元素的值。如果
"done" 为
true ,这是迭代器的返回值(如果提供了返回值)。如果迭代器没有返回值,"value" 为
undefined 。在这种情况下,如果符合对象没有显式继承的 "value" 属性,则
"value" 属性可能缺失。
27.1.2 %IteratorPrototype% 对象
%IteratorPrototype% 对象:
注
本规范中所有实现 Iterator 接口的对象也都继承自 %IteratorPrototype%。 ECMAScript 代码也可以定义继承自 %IteratorPrototype%
的对象。%IteratorPrototype% 对象提供了一个可以为所有迭代器对象添加额外方法的地方。
以下表达式是 ECMAScript 代码访问 %IteratorPrototype% 对象的一种方式:
Object .getPrototypeOf (Object .getPrototypeOf ([][Symbol .iterator ]()))
27.1.2.1 %IteratorPrototype% [ @@iterator ] ( )
调用此函数时执行以下步骤:
1. 返回 this 值。
此函数的 "name" 属性值为 "[Symbol.iterator]" 。
27.1.3 %AsyncIteratorPrototype% 对象
%AsyncIteratorPrototype% 对象:
注
本规范中所有实现 AsyncIterator 接口的对象也都继承自 %AsyncIteratorPrototype%。 ECMAScript 代码也可以定义继承自
%AsyncIteratorPrototype% 的对象。%AsyncIteratorPrototype% 对象提供了一个可以为所有异步迭代器对象添加额外方法的地方。
27.1.3.1 %AsyncIteratorPrototype% [ @@asyncIterator ] ( )
调用此函数时执行以下步骤:
1. 返回 this 值。
此函数的 "name" 属性值为 "[Symbol.asyncIterator]" 。
27.1.4 异步从同步迭代器对象
异步从同步迭代器对象是一个异步迭代器,它适配一个特定的同步迭代器。异步从同步迭代器对象没有命名的 构造函数 。相反,异步从同步迭代器对象是通过 CreateAsyncFromSyncIterator
抽象操作根据需要创建的。
27.1.4.1 创建异步迭代器( CreateAsyncFromSyncIterator )(
syncIteratorRecord )
抽象操作 CreateAsyncFromSyncIterator 接受参数 syncIteratorRecord (一个
迭代器记录 ),并返回
一个迭代器记录 。它用于从同步的
迭代器记录 创建异步迭代器记录。调用时执行以下步骤:
1. 让 asyncIterator 成为 OrdinaryObjectCreate (%AsyncFromSyncIteratorPrototype% ,
« [[SyncIteratorRecord]] »)。
2. 将 asyncIterator .[[SyncIteratorRecord]] 设置为 syncIteratorRecord 。
3. 让 nextMethod 为 ! Get (asyncIterator ,
"next" )。
4. 让 iteratorRecord 成为 迭代器记录 { [[Iterator]] : asyncIterator , [[NextMethod]] :
nextMethod , [[Done]] : false }。
5. 返回 iteratorRecord 。
27.1.4.2 %AsyncFromSyncIteratorPrototype% 对象
%AsyncFromSyncIteratorPrototype% 对象:
27.1.4.2.1 %AsyncFromSyncIteratorPrototype%.next ( [ value ] )
1. 让 O 成为 this 值。
2. 断言 :O 是一个对象 ,并且具有一个 [[SyncIteratorRecord]] 内部插槽。
3. 让 promiseCapability 为 ! NewPromiseCapability (%Promise% ).
4. 让 syncIteratorRecord 为 O .[[SyncIteratorRecord]] 。
5. 如果 value 存在,则
a. 让 result 为 Completion (IteratorNext (syncIteratorRecord ,
value )).
6. 否则,
a. 让 result 为 Completion (IteratorNext (syncIteratorRecord )).
7. IfAbruptRejectPromise (result ,
promiseCapability ).
8. 返回 AsyncFromSyncIteratorContinuation (result ,
promiseCapability ).
27.1.4.2.2 %AsyncFromSyncIteratorPrototype%.return ( [ value ]
)
1. 让 O 成为 this 值。
2. 断言 :O 是一个对象 ,并且具有一个 [[SyncIteratorRecord]] 内部插槽。
3. 让 promiseCapability 为 ! NewPromiseCapability (%Promise% ).
4. 让 syncIterator 为 O .[[SyncIteratorRecord]] .[[Iterator]] 。
5. 让 return 为 Completion (GetMethod (syncIterator ,
"return" )).
6. IfAbruptRejectPromise (return ,
promiseCapability ).
7. 如果 return 是 undefined ,则
a. 让 iterResult 为 CreateIterResultObject (value ,
true ).
b. 执行 ! Call (promiseCapability .[[Resolve]] , undefined , « iterResult »).
c. 返回 promiseCapability .[[Promise]] 。
8. 如果 value 存在,则
a. 让 result 为 Completion (Call (return , syncIterator , «
value »)).
9. 否则,
a. 让 result 为 Completion (Call (return , syncIterator )).
10. IfAbruptRejectPromise (result ,
promiseCapability ).
11. 如果 result 不是一个对象 ,则
a. 执行 ! Call (promiseCapability .[[Reject]] , undefined , « 新创建的
TypeError 对象 »).
b. 返回 promiseCapability .[[Promise]] 。
12. 返回 AsyncFromSyncIteratorContinuation (result ,
promiseCapability ).
27.1.4.2.3 %AsyncFromSyncIteratorPrototype%.throw ( [ value ] )
注
1. 让 O 成为 this 值。
2. 断言 :O 是一个对象 ,并且具有一个 [[SyncIteratorRecord]] 内部插槽。
3. 让 promiseCapability 为 ! NewPromiseCapability (%Promise% ).
4. 让 syncIterator 为 O .[[SyncIteratorRecord]] .[[Iterator]] 。
5. 让 throw 为 Completion (GetMethod (syncIterator ,
"throw" )).
6. IfAbruptRejectPromise (throw ,
promiseCapability ).
7. 如果 throw 是 undefined ,则
a. 执行 ! Call (promiseCapability .[[Reject]] , undefined , « value »).
b. 返回 promiseCapability .[[Promise]] 。
8. 如果 value 存在,则
a. 让 result 为 Completion (Call (throw , syncIterator , «
value »)).
9. 否则,
a. 让 result 为 Completion (Call (throw , syncIterator )).
10. IfAbruptRejectPromise (result ,
promiseCapability ).
11. 如果 result 不是一个对象 ,则
a. 执行 ! Call (promiseCapability .[[Reject]] , undefined , « 新创建的
TypeError 对象 »).
b. 返回 promiseCapability .[[Promise]] 。
12. 返回 AsyncFromSyncIteratorContinuation (result ,
promiseCapability ).
27.1.4.3 异步-从同步迭代器实例的属性
异步-从同步迭代器实例是 普通对象 ,它们继承了来自 %AsyncFromSyncIteratorPrototype%
内在对象的属性。异步-从同步迭代器实例最初是通过内部插槽列表创建的,这些插槽在 表
84 中列出。异步-从同步迭代器实例无法从 ECMAScript 代码中直接观察。
表 84:异步-从同步迭代器实例的内部插槽
内部插槽
类型
描述
[[SyncIteratorRecord]]
一个 迭代器记录
表示正在被适配的原始同步迭代器。
27.1.4.4 AsyncFromSyncIteratorContinuation ( result ,
promiseCapability )
抽象操作 AsyncFromSyncIteratorContinuation 接受两个参数 result (一个对象)和 promiseCapability (一个
PromiseCapability
Record ,用于内在的 %Promise% ),并返回一个
Promise。调用时执行以下步骤:
1. 注意:因为 promiseCapability 源自内在的 %Promise% ,所以在下面使用的
IfAbruptRejectPromise 调用
promiseCapability .[[Reject]] 是保证不会抛出异常的。
2. 令 done 为 Completion (IteratorComplete (result ))。
3. IfAbruptRejectPromise (done ,
promiseCapability ).
4. 令 value 为 Completion (IteratorValue (result ))。
5. IfAbruptRejectPromise (value ,
promiseCapability ).
6. 令 valueWrapper 为 Completion (PromiseResolve (%Promise% ,
value ))。
7. IfAbruptRejectPromise (valueWrapper ,
promiseCapability ).
8. 令 unwrap 为一个新的 抽象闭包 ,参数为
(v ),它捕获 done 并在调用时执行以下步骤:
a. 返回 CreateIterResultObject (v ,
done )。
9. 令 onFulfilled 为 CreateBuiltinFunction (unwrap ,
1, "" , « »).
10. 注意:onFulfilled 用于处理 IteratorResult 对象的
"value" 属性,以等待其值(如果它是一个 Promise)并将结果重新包装在一个新的 "解包" IteratorResult 对象中。
11. 执行 PerformPromiseThen (valueWrapper ,
onFulfilled , undefined , promiseCapability ).
12. 返回 promiseCapability .[[Promise]] 。
27.2 Promise 对象
Promise 是一个对象,用作延迟(可能是异步)计算的最终结果的占位符。
任何 Promise 都处于三种互斥状态之一:已兑现 、已拒绝 和 待定 :
如果 p.then(f, r)
会立即排队一个 任务 来调用函数 f
,那么 Promise p
就是已兑现的。
如果 p.then(f, r)
会立即排队一个 任务 来调用函数 r
,那么 Promise p
就是已拒绝的。
如果 Promise 既不是已兑现也不是已拒绝,则它是待定的。
如果一个 Promise 不是待定的,即它是已兑现的或已拒绝的,那么它被称为 已解决 。
如果一个 Promise 是已解决的,或者它已经被“锁定”以匹配另一个 Promise 的状态,那么它是 已解决 的。尝试解决或拒绝一个已解决的 Promise 是没有效果的。如果一个 Promise
没有被解决,则它是 未解决 的。未解决的 Promise 始终处于待定状态。已解决的 Promise 可能是待定的、已兑现的或已拒绝的。
27.2.1 Promise 抽象操作
27.2.1.1 PromiseCapability 记录
PromiseCapability 记录 是一种
记录
值,用于封装一个 Promise 或类似 Promise 的对象,以及能够解析或拒绝该 Promise 的函数。
PromiseCapability 记录由 NewPromiseCapability
抽象操作生成。
PromiseCapability 记录包含在 表 85
中列出的字段。
表 85: PromiseCapability 记录
字段
字段名称
值
含义
[[Promise]]
一个对象
一个可用作 Promise 的对象。
[[Resolve]]
一个 函数对象
用于解析给定 Promise 的函数。
[[Reject]]
一个 函数对象
用于拒绝给定 Promise 的函数。
27.2.1.1.1 IfAbruptRejectPromise ( value ,
capability
)
IfAbruptRejectPromise 是对使用 PromiseCapability 记录
的一系列算法步骤的简写形式。一个形式如下的算法步骤:
1. IfAbruptRejectPromise (value ,
capability ).
意味着与以下内容相同:
1. 断言 : value 是一个
完成记录 。
2. 如果 value 是一个 突发完成 ,则
a. 执行 ? 调用 (capability .[[Reject]] , undefined , « value .[[Value]] »).
b. 返回 capability .[[Promise]] .
3. 否则,
a. 将 value 设置为 ! value 。
27.2.1.2 PromiseReaction 记录
PromiseReaction 记录 是一种 记录
值,用于存储关于 Promise 在变为解决或拒绝时应如何反应的信息。PromiseReaction 记录由 PerformPromiseThen
抽象操作生成,并由 抽象闭包 使用,该闭包由
NewPromiseReactionJob
返回。
PromiseReaction 记录具有在 表 86
中列出的字段。
表 86: PromiseReaction 记录 字段
字段名称
值
含义
[[Capability]]
一个 PromiseCapability
记录 或 undefined
提供反应处理程序的 Promise 的能力。
[[Type]]
fulfill 或 reject
[[Type]] 用于当 [[Handler]] 为
empty 时,允许根据解决类型进行特定行为。
[[Handler]]
一个 JobCallback 记录 或
empty
应应用于传入值的函数,其返回值将决定派生 Promise 的处理方式。如果 [[Handler]] 为
empty ,将使用一个依赖于 [[Type]] 值的函数。
27.2.1.3 创建解析函数 ( promise )
抽象操作 CreateResolvingFunctions 接受参数 promise (一个 Promise)并返回一个 记录 ,其中包含字段 [[Resolve]] (一个 函数对象 )和 [[Reject]] (一个 函数对象 )。调用时执行以下步骤:
1. 让 alreadyResolved 成为记录 { [[Value]] : false }。
2. 让 stepsResolve 为在 Promise Resolve
Functions 中定义的算法步骤。
3. 让 lengthResolve 为 Promise Resolve
Functions 中函数定义的非可选参数的数量。
4. 让 resolve 为 CreateBuiltinFunction (stepsResolve ,
lengthResolve , "" , « [[Promise]] , [[AlreadyResolved]] »)。
5. 将 resolve .[[Promise]] 设置为
promise 。
6. 将 resolve .[[AlreadyResolved]]
设置为 alreadyResolved 。
7. 让 stepsReject 为在 Promise Reject
Functions 中定义的算法步骤。
8. 让 lengthReject 为 Promise Reject
Functions 中函数定义的非可选参数的数量。
9. 让 reject 为 CreateBuiltinFunction (stepsReject ,
lengthReject , "" , « [[Promise]] , [[AlreadyResolved]] »)。
10. 将 reject .[[Promise]] 设置为
promise 。
11. 将 reject .[[AlreadyResolved]]
设置为 alreadyResolved 。
12. 返回记录 { [[Resolve]] : resolve ,
[[Reject]] : reject }。
27.2.1.3.1 Promise 拒绝函数
Promise 拒绝函数是一个匿名内置函数,具有 [[Promise]] 和 [[AlreadyResolved]] 内部槽位。
当 Promise 拒绝函数以参数 reason 调用时,执行以下步骤:
1. 让 F 成为 活动函数对象 。
2. 断言 : F 具有 [[Promise]] 内部槽位,其值 是一个对象 。
3. 让 promise 为 F .[[Promise]] 。
4. 让 alreadyResolved 为 F .[[AlreadyResolved]] 。
5. 如果 alreadyResolved .[[Value]] 为 true ,则返回 undefined 。
6. 将 alreadyResolved .[[Value]]
设置为 true 。
7. 执行 RejectPromise (promise ,
reason )。
8. 返回 undefined 。
Promise 拒绝函数的 "length" 属性为 1 𝔽 。
27.2.1.3.2 Promise 解析函数
Promise 解析函数是一个匿名内置函数,具有 [[Promise]] 和 [[AlreadyResolved]] 内部槽位。
当 Promise 解析函数以参数 resolution 调用时,执行以下步骤:
1. 让
F 成为 活动函数对象 。
2. 断言 : F 具有 [[Promise]] 内部槽位,其值 是一个对象 。
3. 让 promise 为 F .[[Promise]] 。
4. 让 alreadyResolved 为 F .[[AlreadyResolved]] 。
5. 如果 alreadyResolved .[[Value]] 为 true ,则返回 undefined 。
6. 将 alreadyResolved .[[Value]]
设置为 true 。
7. 如果 resolution 为 promise ,则执行 Promise Resolve
Functions 中的算法步骤,将 resolution 作为参数调用。
8. 否则,如果 resolution 是一个对象并且具有 thenable 的特性,则执行 Promise Resolve
Functions 中的算法步骤,将 resolution 的 then 方法作为参数调用。
9. 否则,执行 Promise Resolve
Functions 中的算法步骤,将 resolution 作为参数调用。
10. 返回 undefined 。
Promise 解析函数的 "length" 属性为 1 𝔽 。
27.2.1.4 FulfillPromise ( promise , value )
抽象操作 FulfillPromise 接受参数 promise (一个 Promise)和 value (一个 ECMAScript 语言值 ),并返回
unused 。调用时执行以下步骤:
1. 断言 : promise .[[PromiseState]] 的值是 pending 。
2. 让 reactions 为 promise .[[PromiseFulfillReactions]] 。
3. 将 promise .[[PromiseResult]]
设置为 value 。
4. 将 promise .[[PromiseFulfillReactions]] 设置为 undefined 。
5. 将 promise .[[PromiseRejectReactions]] 设置为 undefined 。
6. 将 promise .[[PromiseState]]
设置为 fulfilled 。
7. 执行 TriggerPromiseReactions (reactions ,
value )。
8. 返回 unused 。
27.2.1.5 NewPromiseCapability ( C )
抽象操作 NewPromiseCapability 接受参数 C (一个 ECMAScript
语言值 ),并返回一个 正常完成记录 ,其中包含一个
PromiseCapability
记录 ,或者一个 抛出完成记录 。它尝试将
C 作为 构造函数 使用,以类似于内置 Promise 构造函数 的方式创建一个 promise,并提取其
resolve
和 reject
函数。这个 promise 以及 resolve
和 reject
函数将用于初始化一个新的 PromiseCapability
记录 。调用时执行以下步骤:
1. 如果 IsConstructor (C ) 为
false ,则抛出一个 TypeError 异常。
2. 注意:C 被假设为一个 构造函数 ,支持 Promise
构造函数 的参数约定(见 27.2.3.1 )。
3. 让 resolvingFunctions 为一个 记录 { [[Resolve]] : undefined ,[[Reject]] :
undefined }。
4. 让 executorClosure 为一个新的 抽象闭包 ,参数为 (resolve ,
reject ),捕获 resolvingFunctions 并执行以下步骤:
a. 如果 resolvingFunctions .[[Resolve]] 不为 undefined ,则抛出一个
TypeError 异常。
b. 如果 resolvingFunctions .[[Reject]] 不为 undefined ,则抛出一个
TypeError 异常。
c. 将 resolvingFunctions .[[Resolve]] 设置为 resolve 。
d. 将 resolvingFunctions .[[Reject]] 设置为 reject 。
e. 返回 undefined 。
5. 让 executor 为 CreateBuiltinFunction (executorClosure ,
2, "" ,« »)。
6. 让 promise 为 ? Construct (C ,« executor »)。
7. 如果 IsCallable (resolvingFunctions .[[Resolve]] ) 为 false ,则抛出一个 TypeError 异常。
8. 如果 IsCallable (resolvingFunctions .[[Reject]] ) 为 false ,则抛出一个 TypeError 异常。
9. 返回 PromiseCapability
记录 { [[Promise]] : promise ,[[Resolve]] : resolvingFunctions .[[Resolve]] ,[[Reject]] :
resolvingFunctions .[[Reject]] }。
注
此抽象操作支持 Promise 子类化,因为它对任何 构造函数 是通用的,只要该构造
函数以与 Promise 构造函数 相同的方式调用传入的 executor 函数参数。它用于将
Promise 构造函数 的静态方法泛化到任何子类。
27.2.1.6 IsPromise ( x )
抽象操作 IsPromise 接受参数 x (一个 ECMAScript
语言值 ),并返回一个布尔值。它检查一个对象是否具有 promise 标识。调用时执行以下步骤:
1. 如果 x 不是一个对象 ,则返回
false 。
2. 如果 x 没有 [[PromiseState]]
内部槽,则返回 false 。
3. 返回 true 。
27.2.1.7 RejectPromise ( promise , reason )
抽象操作 RejectPromise 接受参数 promise (一个 Promise)和 reason (一个 ECMAScript 语言值 ),并返回
unused 。调用时执行以下步骤:
1. Assert :promise .[[PromiseState]] 的值为 pending 。
2. 设 reactions 为 promise .[[PromiseRejectReactions]] 。
3. 将 promise .[[PromiseResult]]
设置为 reason 。
4. 将 promise .[[PromiseFulfillReactions]] 设置为 undefined 。
5. 将 promise .[[PromiseRejectReactions]] 设置为 undefined 。
6. 将 promise .[[PromiseState]]
设置为 rejected 。
7. 如果 promise .[[PromiseIsHandled]] 为 false ,执行 HostPromiseRejectionTracker (promise ,
"reject" )。
8. 执行 TriggerPromiseReactions (reactions ,
reason )。
9. 返回 unused 。
27.2.1.8 TriggerPromiseReactions ( reactions , argument
)
抽象操作 TriggerPromiseReactions 接受参数 reactions (一个 列表 的 PromiseReaction 记录 )和
argument (一个 ECMAScript 语言值 ),并返回
unused 。它为 reactions 中的每个记录排队一个新的 任务 。每个这样的 任务 处理 [[Type]] 和 [[Handler]] 的 PromiseReaction 记录 ,如果 [[Handler]] 不是 empty ,则调用它并传递给定的参数。如果 [[Handler]] 是 empty ,行为由 [[Type]]
决定。调用时执行以下步骤:
1. 对于 reactions 中的每个元素 reaction ,执行:
a. 设 job 为 NewPromiseReactionJob (reaction ,
argument )。
b. 执行 HostEnqueuePromiseJob (job .[[Job]] , job .[[Realm]] )。
2. 返回 unused 。
27.2.1.9 HostPromiseRejectionTracker ( promise ,
operation )
host-defined 抽象操作
HostPromiseRejectionTracker 接受参数 promise (一个 Promise)和
operation ("reject" 或 "handle" ),并返回
unused 。它允许 宿主环境 跟踪 promise 拒绝情况。
HostPromiseRejectionTracker 的默认实现是返回 unused 。
Note 1
HostPromiseRejectionTracker 在以下两种情况下被调用:
当一个 promise 被拒绝且没有任何处理程序时,它会以 operation 参数设置为 "reject" 的形式被调用。
当一个处理程序第一次被添加到一个被拒绝的 promise 时,它会以 operation 参数设置为 "handle" 的形式被调用。
HostPromiseRejectionTracker 的典型实现可能会尝试通知开发人员未处理的拒绝,同时也要注意在新处理程序被附加时通知开发人员如果之前的通知被无效化。
Note 2
如果 operation 是 "handle" ,实现不应该以任何干扰垃圾回收的方式持有对 promise 的引用。如果
operation 是 "reject" ,实现可以持有对 promise
的引用,因为预计拒绝情况将会很少且不会出现在热代码路径上。
27.2.2 Promise Jobs
27.2.2.1 NewPromiseReactionJob ( reaction ,
argument
)
抽象操作 NewPromiseReactionJob 接受两个参数 reaction (一个 PromiseReaction
Record )和 argument (一个 ECMAScript
语言值 ),并返回一个 记录 ,
其中包含字段 [[Job]] (一个 Job 抽象闭包 )
和 [[Realm]] (一个 Realm 记录 或 null )。
它返回一个新的 Job
抽象闭包 ,
该闭包应用适当的处理程序到传入值,并使用处理程序的返回值来解决或拒绝与该处理程序关联的派生承诺。它执行以下步骤:
1. 让 job 成为一个新的 Job 抽象闭包 ,该闭包无参数,
捕获 reaction 和 argument ,并在调用时执行以下步骤:
a. 让 promiseCapability 成为
reaction .[[Capability]] 。
b. 让 type 成为 reaction .[[Type]] 。
c. 让 handler 成为 reaction .[[Handler]] 。
d. 如果 handler 是 empty ,
则
i. 如果 type 是 fulfill ,
则
1. 让 handlerResult 成为 NormalCompletion (argument )。
ii. 否则,
1. Assert :type 是
reject 。
2. 让 handlerResult 成为 ThrowCompletion (argument )。
e. 否则,
i. 让 handlerResult 成为 Completion (HostCallJobCallback (handler ,
undefined , « argument »))。
f. 如果 promiseCapability 是
undefined ,则
i. Assert :
handlerResult 不是一个 异常完成 。
ii. 返回 empty 。
g. Assert :
promiseCapability 是一个 PromiseCapability
Record 。
h. 如果 handlerResult 是一个 异常完成 ,则
i. 返回 ? Call (promiseCapability .[[Reject]] , undefined , «
handlerResult .[[Value]] »)。
i. 否则,
i. 返回 ? Call (promiseCapability .[[Resolve]] , undefined , «
handlerResult .[[Value]] »)。
2. 让 handlerRealm 成为 null 。
3. 如果 reaction .[[Handler]]
不是
empty ,则
a. 让 getHandlerRealmResult 成为 Completion (GetFunctionRealm (reaction .[[Handler]] .[[Callback]] ))。
b. 如果 getHandlerRealmResult 是一个 正常完成 ,将
handlerRealm 设为
getHandlerRealmResult .[[Value]] 。
c. 否则,将 handlerRealm 设为 当前 Realm
记录 。
d. 注意:handlerRealm 除非处理程序是
undefined ,否则永远不会是 null 。当处理程序是一个已撤销的代理且没有 ECMAScript
代码运行时,handlerRealm 用于创建错误对象。
4. 返回 记录
{ [[Job]] : job , [[Realm]] :
handlerRealm }。
27.2.2.2 NewPromiseResolveThenableJob ( promiseToResolve ,
thenable , then )
抽象操作 NewPromiseResolveThenableJob 接受三个参数 promiseToResolve (一个
Promise),thenable (一个对象)和 then (一个 JobCallback
记录 ),并返回一个 记录 ,
其中包含字段 [[Job]] (一个 Job 抽象闭包 )
和 [[Realm]] (一个 Realm 记录 )。它执行以下步骤:
1. 让 job 成为一个新的 Job 抽象闭包 ,该闭包无参数,
捕获 promiseToResolve 、thenable 和 then ,并在调用时执行以下步骤:
a. 让 resolvingFunctions 成为 CreateResolvingFunctions (promiseToResolve )。
b. 让 thenCallResult 成为 Completion (HostCallJobCallback (then ,
thenable ,
«
resolvingFunctions .[[Resolve]] ,
resolvingFunctions .[[Reject]] »))。
c. 如果 thenCallResult 是一个 异常完成 ,则
i. 返回 ? Call (resolvingFunctions .[[Reject]] , undefined , «
thenCallResult .[[Value]] »)。
d. 返回 ? thenCallResult 。
2. 让 getThenRealmResult 成为 Completion (GetFunctionRealm (then .[[Callback]] ))。
3. 如果 getThenRealmResult 是一个 正常完成 ,则让
thenRealm 成为 getThenRealmResult .[[Value]] 。
4. 否则,让 thenRealm 成为 当前 Realm 记录 。
5. 注意:thenRealm 永远不会是 null 。
当 then .[[Callback]] 是一个被撤销的 Proxy 且没有代码运行时,thenRealm
用于创建错误对象。
6. 返回 记录
{ [[Job]] : job , [[Realm]] :
thenRealm }。
注
这个 Job
使用提供的 thenable 及其
then
方法来解决给定的承诺。这个过程必须作为一个 Job 来确保
then
方法的评估在任何围绕代码的评估完成之后进行。
27.2.3 Promise 构造函数
Promise 构造函数 :
是 %Promise% 。
是 "Promise" 属性的初始值的 全局对象 。
在作为 构造函数 调用时,创建并初始化一个新的 Promise。
不应被作为函数调用,若以这种方式调用将抛出异常。
可以用作类定义的 extends
子句中的值。继承指定 Promise 行为的子类 构造函数 必须包括对 Promise 构造函数
的 super
调用,以使用支持 Promise
和 Promise.prototype
内置方法所需的内部状态来创建和初始化子类实例。
27.2.3.1 Promise ( executor )
该函数在调用时执行以下步骤:
1. 如果 NewTarget 是 undefined ,则抛出
TypeError 异常。
2. 如果 IsCallable (executor ) 是
false ,则抛出 TypeError 异常。
3. 让 promise 成为 ? OrdinaryCreateFromConstructor (NewTarget,
"%Promise.prototype%" , « [[PromiseState]] , [[PromiseResult]] , [[PromiseFulfillReactions]] ,
[[PromiseRejectReactions]] , [[PromiseIsHandled]] »)。
4. 将 promise .[[PromiseState]]
设置为 pending 。
5. 将 promise .[[PromiseFulfillReactions]] 设置为一个新的空 列表 。
6. 将 promise .[[PromiseRejectReactions]] 设置为一个新的空 列表 。
7. 将 promise .[[PromiseIsHandled]] 设置为 false 。
8. 让 resolvingFunctions 成为 CreateResolvingFunctions (promise )。
9. 让 completion 成为 Completion (Call (executor , undefined , «
resolvingFunctions .[[Resolve]] ,
resolvingFunctions .[[Reject]] »))。
10. 如果 completion 是 异常完成 ,则
a. 执行 ? Call (resolvingFunctions .[[Reject]] , undefined , « completion .[[Value]] »)。
11. 返回 promise 。
注
executor 参数必须是 函数对象 。它用于启动和报告可能被延迟的操作的完成。
executor 被调用时带有两个参数:resolve 和 reject 。这些是可以由 executor
函数使用的函数,用于报告延迟计算的最终完成或失败。 从 executor 函数返回并不意味着延迟操作已完成,而仅表示请求已接受以最终执行延迟操作。
传递给 executor 函数的 resolve 函数接受一个参数。 executor 代码可能最终调用
resolve 函数以指示希望解析关联的 Promise。 传递给 resolve 函数的参数代表延迟操作的最终值,可以是实际的履行值,也可以是另一个
Promise,该 Promise 将在履行时提供该值。
传递给 executor 函数的 reject 函数接受一个参数。 executor 代码可能最终调用
reject 函数以指示关联的 Promise 被拒绝且永远不会被履行。 传递给 reject 函数的参数用作 Promise 的拒绝值。 通常,它将是一个
Error 对象。
传递给 executor 函数的 resolve 和 reject 函数具有实际解析和拒绝关联 Promise 的能力。 子类可能有不同的 构造函数 行为,传递定制的 resolve 和 reject 值。
27.2.4 Promise 构造函数的属性
Promise 构造函数 :
27.2.4.1 Promise.all ( iterable )
此函数返回一个新的 promise,该 promise 会被一个包含传入的 promises 的 fulfillment 值的数组所兑现,或者被第一个拒绝的传入 promise
的原因所拒绝。它在运行此算法时会将传入的 iterable 中的所有元素解析为 promises。
1. 让 C 为 this 值。
2. 让 promiseCapability 为 ? NewPromiseCapability (C )。
3. 让 promiseResolve 为 Completion (GetPromiseResolve (C ))。
4. IfAbruptRejectPromise (promiseResolve ,
promiseCapability )。
5. 让 iteratorRecord 为 Completion (GetIterator (iterable ,
sync ))。
6. IfAbruptRejectPromise (iteratorRecord ,
promiseCapability )。
7. 让 result 为 Completion (PerformPromiseAll (iteratorRecord , C ,
promiseCapability , promiseResolve ))。
8. 如果 result 是一个 突发完成 ,则
a. 如果 iteratorRecord .[[Done]] 为 false ,将 result 设置为 Completion (IteratorClose (iteratorRecord ,
result ))。
b. IfAbruptRejectPromise (result ,
promiseCapability )。
9. 返回 ? result 。
注
此函数要求其 this 值为一个 构造函数
函数,并且支持 Promise 构造函数 的参数约定。
27.2.4.1.1 GetPromiseResolve ( promiseConstructor )
抽象操作 GetPromiseResolve 接受参数 promiseConstructor (一个 构造函数 )并返回一个 正常完成 ,其中包含一个
函数对象 或一个 抛出完成 。调用时执行以下步骤:
1. 让 promiseResolve 为 ? Get (promiseConstructor ,
"resolve" )。
2. 如果 IsCallable (promiseResolve )
为 false ,则抛出 TypeError 异常。
3. 返回 promiseResolve 。
27.2.4.1.2 PerformPromiseAll ( iteratorRecord ,
promiseConstructor , promiseCapability , promiseResolve )
抽象操作 PerformPromiseAll 接受参数
iteratorRecord 、promiseConstructor 、promiseCapability 和
promiseResolve 。它会处理 iteratorRecord 中的每个项,并在完成时解决
promiseCapability 。如果在处理时遇到拒绝,promiseCapability 会被拒绝。
1. 让 values 为一个空的 列表 。
2. 让 index 为 0 。
3. 让 next 为 IteratorStep (iteratorRecord )。
4. 如果 next 为 false ,则
a. 将 values 设置为 Completion (ResolvePromiseAll (values ,
promiseCapability ))。
b. 返回 values 。
5. 让 nextValue 为 IteratorValue (next )。
6. 让 nextPromise 为 ? PromiseResolve (promiseConstructor ,
nextValue )。
7. IfAbruptRejectPromise (nextPromise ,
promiseCapability )。
8. 将 values [index ] 设置为
nextPromise 。
9. 让 index 增加 1 。
10. 返回 ? PerformPromiseAll (iteratorRecord ,
promiseConstructor , promiseCapability , promiseResolve )。
27.2.4.1.3 Promise.all
Resolve Element Functions
Promise.all
解析元素函数是一个用于解析特定Promise.all
元素的匿名内置函数。每个Promise.all
解析元素函数都有[[Index]] 、[[Values]] 、[[Capability]] 、[[RemainingElements]] 和[[AlreadyCalled]] 内部槽。
当一个Promise.all
解析元素函数被调用并传入参数x 时,执行以下步骤:
1. 令F 为活动函数对象 。
2. 如果F 的[[AlreadyCalled]] 为true ,则返回undefined 。
3. 将F 的[[AlreadyCalled]] 设置为true 。
4. 令index 为F 的[[Index]] 。
5. 令values 为F 的[[Values]] 。
6. 令promiseCapability 为F 的[[Capability]] 。
7. 令remainingElementsCount 为F 的[[RemainingElements]] 。
8. 将values [index ]设置为x 。
9. 将remainingElementsCount 的[[Value]] 设置为remainingElementsCount 的[[Value]] - 1。
10. 如果remainingElementsCount 的[[Value]] 为0,则
a. 令valuesArray 为CreateArrayFromList (values )。
b. 返回 ? Call (promiseCapability 的[[Resolve]] ,undefined ,« valuesArray »)。
11. 返回undefined 。
Promise.all
解析元素函数的"length" 属性是1 𝔽 。
27.2.4.2 Promise.allSettled ( iterable )
此函数返回一个 promise,该 promise 会被一个包含所有传入 promise 状态快照的数组兑现,但只有在所有原始 promise 都已完成(即已兑现或拒绝)之后。它在运行此算法时会将传入的
iterable 中的所有元素解析为 promises。
1. 让 C 为 this 值。
2. 让 promiseCapability 为 ? NewPromiseCapability (C )。
3. 让 promiseResolve 为 Completion (GetPromiseResolve (C ))。
4. IfAbruptRejectPromise (promiseResolve ,
promiseCapability )。
5. 让 iteratorRecord 为 Completion (GetIterator (iterable ,
sync ))。
6. IfAbruptRejectPromise (iteratorRecord ,
promiseCapability )。
7. 让 result 为 Completion (PerformPromiseAllSettled (iteratorRecord ,
C , promiseCapability , promiseResolve ))。
8. 如果 result 是一个 突发完成 ,则
a. 如果 iteratorRecord .[[Done]] 为 false ,将 result 设置为 Completion (IteratorClose (iteratorRecord ,
result ))。
b. IfAbruptRejectPromise (result ,
promiseCapability )。
9. 返回 ? result 。
注
此函数要求其 this 值为一个 构造函数
函数,并且支持 Promise 构造函数 的参数约定。
27.2.4.2.1 PerformPromiseAllSettled ( iteratorRecord ,
constructor , resultCapability , promiseResolve )
抽象操作 PerformPromiseAllSettled 接受参数 iteratorRecord (一个 Iterator
Record ),
constructor (一个 构造函数 ),
resultCapability (一个 PromiseCapability
Record ),以及 promiseResolve (一个 函数对象 ),并返回一个包含
正常完成 的
ECMAScript 语言值 或一个
抛出完成 。调用时执行以下步骤:
1. 让 values 为一个新的
空 列表 。
2. 让 remainingElementsCount 为 记录
{ [[Value]] : 1 }。
3. 让 index 为 0。
4. 重复,
a. 让 next 为 ? IteratorStepValue (iteratorRecord )。
b. 如果 next 是 done ,则
i. 将 remainingElementsCount .[[Value]] 设置为 remainingElementsCount .[[Value]] - 1。
ii. 如果 remainingElementsCount .[[Value]] 为 0,则
1. 让 valuesArray 为 CreateArrayFromList (values )。
2. 执行 ? Call (resultCapability .[[Resolve]] , undefined , «
valuesArray »)。
iii. 返回 resultCapability .[[Promise]] 。
c. 将 undefined 添加到
values 中。
d. 让 nextPromise 为 ? Call (promiseResolve ,
constructor ,
«
next »)。
e. 让 stepsFulfilled 为定义在 Promise.allSettled
解决元素函数 中的算法步骤。
f. 让 lengthFulfilled 为定义在 Promise.allSettled
解决元素函数 中的函数定义的非可选参数数量。
g. 让 onFulfilled 为 CreateBuiltinFunction (stepsFulfilled ,
lengthFulfilled , "" , « [[AlreadyCalled]] ,
[[Index]] , [[Values]] , [[Capability]] , [[RemainingElements]] »)。
h. 让 alreadyCalled 为 记录
{ [[Value]] : false }。
i. 将 onFulfilled .[[AlreadyCalled]] 设置为 alreadyCalled 。
j. 将 onFulfilled .[[Index]]
设置为 index 。
k. 将 onFulfilled .[[Values]] 设置为 values 。
l. 将 onFulfilled .[[Capability]] 设置为 resultCapability 。
m. 将 onFulfilled .[[RemainingElements]] 设置为 remainingElementsCount 。
n. 让 stepsRejected 为定义在 Promise.allSettled
拒绝元素函数 中的算法步骤。
o. 让 lengthRejected 为定义在 Promise.allSettled
拒绝元素函数 中的函数定义的非可选参数数量。
p. 让 onRejected 为 CreateBuiltinFunction (stepsRejected ,
lengthRejected , "" , « [[AlreadyCalled]] ,
[[Index]] , [[Values]] , [[Capability]] , [[RemainingElements]] »)。
q. 将 onRejected .[[AlreadyCalled]] 设置为 alreadyCalled 。
r. 将 onRejected .[[Index]]
设置为 index 。
s. 将 onRejected .[[Values]]
设置为 values 。
t. 将 onRejected .[[Capability]] 设置为 resultCapability 。
u. 将 onRejected .[[RemainingElements]] 设置为 remainingElementsCount 。
v. 将 remainingElementsCount .[[Value]] 设置为 remainingElementsCount .[[Value]] + 1。
w. 执行 ? Invoke (nextPromise ,
"then" ,
« onFulfilled , onRejected »)。
x. 将 index 设置为 index + 1。
27.2.4.2.2 Promise.allSettled
解决元素函数
Promise.allSettled
解决元素函数是一个匿名内置函数,用于解决特定的 Promise.allSettled
元素。每个
Promise.allSettled
解决元素函数都有 [[Index]] 、[[Values]] 、[[Capability]] 、[[RemainingElements]] 和 [[AlreadyCalled]] 内部槽。
当调用 Promise.allSettled
解决元素函数并带有参数 x 时,执行以下步骤:
1. 让 F 为 活动函数对象 。
2. 让 alreadyCalled 为 F .[[AlreadyCalled]] 。
3. 如果 alreadyCalled .[[Value]]
为 true ,返回 undefined 。
4. 将 alreadyCalled .[[Value]]
设置为 true 。
5. 让 index 为 F .[[Index]] 。
6. 让 values 为 F .[[Values]] 。
7. 让 promiseCapability 为 F .[[Capability]] 。
8. 让 remainingElementsCount 为 F .[[RemainingElements]] 。
9. 让 obj 为 OrdinaryObjectCreate (%Object.prototype% )。
10. 执行 ! CreateDataPropertyOrThrow (obj ,
"status" , "fulfilled" )。
11. 执行 ! CreateDataPropertyOrThrow (obj ,
"value" , x )。
12. 将 values [index ] 设置为 obj 。
13. 将 remainingElementsCount .[[Value]] 设置为 remainingElementsCount .[[Value]] - 1。
14. 如果 remainingElementsCount .[[Value]] 为 0,则
a. 让 valuesArray 为 CreateArrayFromList (values )。
b. 返回 ? Call (promiseCapability .[[Resolve]] , undefined , «
valuesArray »)。
15. 返回 undefined 。
一个 Promise.allSettled
解决元素函数的 "length" 属性为
1 𝔽 。
27.2.4.2.3 Promise.allSettled
拒绝
元素函数
Promise.allSettled
拒绝元素函数是一个匿名内置函数,用于拒绝特定的 Promise.allSettled
元素。每个
Promise.allSettled
拒绝元素函数都有 [[Index]] 、[[Values]] 、[[Capability]] 、[[RemainingElements]] 和 [[AlreadyCalled]] 内部槽。
当调用 Promise.allSettled
拒绝元素函数并带有参数 x 时,执行以下步骤:
1. 让 F 为 活动函数对象 。
2. 让 alreadyCalled 为 F .[[AlreadyCalled]] 。
3. 如果 alreadyCalled .[[Value]]
为 true ,返回 undefined 。
4. 将 alreadyCalled .[[Value]]
设置为 true 。
5. 让 index 为 F .[[Index]] 。
6. 让 values 为 F .[[Values]] 。
7. 让 promiseCapability 为 F .[[Capability]] 。
8. 让 remainingElementsCount 为 F .[[RemainingElements]] 。
9. 让 obj 为 OrdinaryObjectCreate (%Object.prototype% )。
10. 执行 ! CreateDataPropertyOrThrow (obj ,
"status" , "rejected" )。
11. 执行 ! CreateDataPropertyOrThrow (obj ,
"reason" , x )。
12. 将 values [index ] 设置为 obj 。
13. 将 remainingElementsCount .[[Value]] 设置为 remainingElementsCount .[[Value]] - 1。
14. 如果 remainingElementsCount .[[Value]] 为 0,则
a. 让 valuesArray 为 CreateArrayFromList (values )。
b. 返回 ? Call (promiseCapability .[[Resolve]] , undefined , «
valuesArray »)。
15. 返回 undefined 。
一个 Promise.allSettled
拒绝元素函数的 "length" 属性为
1 𝔽 。
27.2.4.3 Promise.any ( iterable )
此函数返回一个承诺,该承诺由第一个完成的承诺实现,或者如果所有给定的承诺都被拒绝,则由一个持有拒绝原因的 AggregateError
拒绝。它在执行此算法时将传递的可迭代对象的所有元素解析为承诺。
1. 让 C 为 this 值。
2. 让 promiseCapability 为 ? NewPromiseCapability (C ).
3. 让 promiseResolve 为 Completion (GetPromiseResolve (C )).
4. IfAbruptRejectPromise (promiseResolve ,
promiseCapability ).
5. 让 iteratorRecord 为 Completion (GetIterator (iterable ,
sync )).
6. IfAbruptRejectPromise (iteratorRecord ,
promiseCapability ).
7. 让 result 为 Completion (PerformPromiseAny (iteratorRecord , C ,
promiseCapability , promiseResolve )).
8. 如果 result 是 abrupt
completion ,则
a. 如果 iteratorRecord .[[Done]] 为 false ,将 result 设置为 Completion (IteratorClose (iteratorRecord ,
result )).
b. IfAbruptRejectPromise (result ,
promiseCapability ).
9. 返回 ? result 。
注
此函数要求其 this 值为一个支持 Promise
构造函数 的参数约定的构造函数。
27.2.4.3.1 执行 Promise.any ( iteratorRecord ,
constructor , resultCapability , promiseResolve )
抽象操作 PerformPromiseAny 接受以下参数:iteratorRecord (一个 迭代器记录 ),
constructor (一个 构造函数 ),
resultCapability (一个 PromiseCapability
记录 ),
和 promiseResolve (一个 函数对象 ),并返回一个 正常完成 ,
包含一个 ECMAScript 语言值 ,
或一个 抛出完成 。
它在调用时执行以下步骤:
1. 让 errors 为一个新的空 列表 。
2. 让 remainingElementsCount 为 记录
{ [[Value]] : 1 }。
3. 让 index 为 0。
4. 重复,
a. 让 next 为 ? IteratorStepValue (iteratorRecord )。
b. 如果 next 为 done ,则
i. 将 remainingElementsCount .[[Value]] 设置为 remainingElementsCount .[[Value]] - 1。
ii. 如果 remainingElementsCount .[[Value]] = 0,则
1. 让 error 为一个新创建的
AggregateError 对象。
2. 执行 ! DefinePropertyOrThrow (error ,
"errors" , 属性描述符 { [[Configurable]] :
true , [[Enumerable]] :
false , [[Writable]] :
true , [[Value]] : CreateArrayFromList (errors ) })。
3. 返回 ThrowCompletion (error )。
iii. 返回 resultCapability .[[Promise]] 。
c. 将 undefined 附加到 errors 。
d. 让 nextPromise 为 ? Call (promiseResolve ,
constructor ,
« next »)。
e. 让 stepsRejected 为在 Promise.any
拒绝元素函数 中定义的算法步骤。
f. 让 lengthRejected 为在 Promise.any
拒绝元素函数 中函数定义的非可选参数数量。
g. 让 onRejected 为 CreateBuiltinFunction (stepsRejected ,
lengthRejected , "" , « [[AlreadyCalled]] ,
[[Index]] , [[Errors]] , [[Capability]] , [[RemainingElements]] »)。
h. 将 onRejected .[[AlreadyCalled]] 设置为 false 。
i. span>将 onRejected .[[Index]]
设置为 index 。
j. 将 onRejected .[[Errors]]
设置为 errors 。
k. 将 onRejected .[[Capability]] 设置为 resultCapability 。
l. 将 onRejected .[[RemainingElements]] 设置为 remainingElementsCount 。
m. 将 remainingElementsCount .[[Value]] 设置为 remainingElementsCount .[[Value]] + 1。
n. 执行 ? Invoke (nextPromise ,
"then" ,
« resultCapability .[[Resolve]] ,
onRejected »)。
o. 将 index 设置为 index + 1。
27.2.4.3.2 Promise.any
拒绝元素函数
Promise.any
拒绝元素函数是一个匿名内置函数,用于拒绝特定的 Promise.any
元素。每个
Promise.any
拒绝元素函数都有 [[Index]] 、[[Errors]] 、[[Capability]] 、[[RemainingElements]] 和 [[AlreadyCalled]] 内部槽。
当调用 Promise.any
拒绝元素函数并传递参数 x 时,将执行以下步骤:
1. 让 F 为 活动函数对象 。
2. 如果 F .[[AlreadyCalled]] 为
true ,则返回 undefined 。
3. 将 F .[[AlreadyCalled]] 设置为
true 。
4. 让 index 为 F .[[Index]] 。
5. 让 errors 为 F .[[Errors]] 。
6. 让 promiseCapability 为 F .[[Capability]] 。
7. 让 remainingElementsCount 为 F .[[RemainingElements]] 。
8. 将 errors [index ] 设置为 x 。
9. 将 remainingElementsCount .[[Value]] 设置为 remainingElementsCount .[[Value]] - 1。
10. 如果 remainingElementsCount .[[Value]] = 0,则
a. 让 error 为新创建的
AggregateError 对象。
b. 执行 ! DefinePropertyOrThrow (error ,
"errors" , 属性描述符 { [[Configurable]] :
true , [[Enumerable]] : false ,
[[Writable]] : true , [[Value]] : CreateArrayFromList (errors ) })。
c. 返回 ? Call (promiseCapability .[[Reject]] , undefined , « error »)。
11. 返回 undefined 。
Promise.any
拒绝元素函数的 "length" 属性是 1 𝔽 。
27.2.4.4 Promise.prototype
Promise.prototype
的初始值是 Promise
原型对象 。
该属性具有属性 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
false }。
27.2.4.5 Promise.race ( iterable )
此函数返回一个新承诺,该承诺以与第一个完成的承诺相同的方式解决。它在执行此算法时会将传入的 iterable 中的所有元素解析为承诺。
1. 令 C 为 this 值。
2. 令 promiseCapability 为 ? NewPromiseCapability (C )。
3. 令 promiseResolve 为 Completion (GetPromiseResolve (C ))。
4. IfAbruptRejectPromise (promiseResolve ,
promiseCapability )。
5. 令 iteratorRecord 为 Completion (GetIterator (iterable ,
sync ))。
6. IfAbruptRejectPromise (iteratorRecord ,
promiseCapability )。
7. 令 result 为 Completion (PerformPromiseRace (iteratorRecord , C ,
promiseCapability , promiseResolve ))。
8. 如果 result 是一个 急骤完成 ,则
a. 如果 iteratorRecord .[[Done]] 为 false ,将 result 设置为 Completion (IteratorClose (iteratorRecord ,
result ))。
b. IfAbruptRejectPromise (result ,
promiseCapability )。
9. 返回 ? result 。
注 1
如果 iterable 参数不生成任何值或如果 iterable 生成的承诺都未解决,那么此方法返回的待定承诺将永远不会解决。
注 2
此函数期望其 this 值是一个支持承诺 构造函数 参数约定的构造函数。它还期望其
this 值提供一个 resolve
方法。
27.2.4.5.1 PerformPromiseRace ( iteratorRecord ,
constructor , resultCapability , promiseResolve )
抽象操作 PerformPromiseRace 接受参数 iteratorRecord (一个 迭代器记录 )、constructor (一个
构造函数 )、resultCapability (一个
PromiseCapability
记录 )和 promiseResolve (一个 函数对象 ),并返回一个
正常完成 ,其中包含一个
ECMAScript 语言值 ,或者一个
抛出完成 。它执行以下步骤:
1. 重复,
a. 令 next 为 ? IteratorStepValue (iteratorRecord )。
b. 如果 next 为 done ,则
i. 返回 resultCapability .[[Promise]] 。
c. 令 nextPromise 为 ? Call (promiseResolve , constructor ,
« next »)。
d. 执行 ? Invoke (nextPromise ,
"then" , « resultCapability .[[Resolve]] ,
resultCapability .[[Reject]] »)。
27.2.4.6 Promise.reject ( r )
此函数返回一个新承诺,该承诺以传入的参数被拒绝。
1. 令 C 为 this 值。
2. 令 promiseCapability 为 ? NewPromiseCapability (C )。
3. 执行 ? Call (promiseCapability .[[Reject]] , undefined , « r »)。
4. 返回 promiseCapability .[[Promise]] 。
注
此函数期望其 this 值是一个支持承诺 构造函数 参数约定的构造函数。
27.2.4.7 Promise.resolve ( x )
此函数返回一个新承诺,该承诺以传入的参数被解决,或者如果参数本身是由此 构造函数 生成的承诺,则返回该参数。
1. 令 C 为 this 值。
2. 如果 C 不是一个对象 ,则抛出
TypeError 异常。
3. 返回 ? PromiseResolve (C , x )。
注
此函数期望其 this 值是一个支持承诺 构造函数 参数约定的构造函数。
27.2.4.7.1 PromiseResolve ( C , x )
抽象操作 PromiseResolve 接受参数 C (一个 构造函数 )和 x (一个 ECMAScript
语言值 ),并返回一个新的承诺,使用 x 进行解决。它执行以下步骤:
1. 如果 IsPromise (x ) 为
true ,则
a. 令 xConstructor 为 ? Get (x , "constructor" )。
b. 如果 SameValue (xConstructor ,
C ) 为 true ,则返回 x 。
2. 令 promiseCapability 为 ? NewPromiseCapability (C )。
3. 执行 ? Call (promiseCapability .[[Resolve]] , undefined , « x »)。
4. 返回 promiseCapability .[[Promise]] 。
27.2.4.8 Promise.withResolvers ( )
此函数返回一个对象,该对象具有三个属性:一个新的承诺以及与之关联的 resolve
和 reject
函数。
1. 令 C 为 this 值。
2. 令 promiseCapability 为 ? NewPromiseCapability (C )。
3. 令 obj 为 OrdinaryObjectCreate (%Object.prototype% )。
4. 执行 ! CreateDataPropertyOrThrow (obj ,
"promise" , promiseCapability .[[Promise]] )。
5. 执行 ! CreateDataPropertyOrThrow (obj ,
"resolve" , promiseCapability .[[Resolve]] )。
6. 执行 ! CreateDataPropertyOrThrow (obj ,
"reject" , promiseCapability .[[Reject]] )。
7. 返回 obj 。
27.2.4.9 get Promise [ @@species ]
Promise[@@species]
是一个 访问器属性 ,其设置访问器函数为
undefined 。其获取访问器函数在调用时执行以下步骤:
1. 返回 this 值。
该函数的 "name" 属性值为 "get [Symbol.species]" 。
Note
Promise 原型方法通常使用其 this 值的 构造函数 来创建一个派生对象。然而,子类 构造函数 可以通过重新定义其 @@species 属性来覆盖这种默认行为。
27.2.5 Promise 原型对象的属性
Promise 原型对象 :
是 %Promise.prototype% 。
具有一个 [[Prototype]] 内部槽,其值为 %Object.prototype% 。
是一个 普通对象 。
没有 [[PromiseState]] 内部槽或任何其他 Promise 实例的内部槽。
27.2.5.1 Promise.prototype.catch ( onRejected )
该方法在调用时执行以下步骤:
1. 让 promise 为 this 值。
2. 返回 ? Invoke (promise , "then" , «
undefined , onRejected »).
27.2.5.2 Promise.prototype.constructor
Promise.prototype.constructor
的初始值为 %Promise% 。
27.2.5.3 Promise.prototype.finally ( onFinally )
该方法在调用时执行以下步骤:
1. 让 promise 为 this 值。
2. 如果 promise 不是一个对象 ,则抛出
TypeError 异常。
3. 让 C 为 ? SpeciesConstructor (promise , %Promise% ).
4. Assert : IsConstructor (C )
为 true 。
5. 如果 IsCallable (onFinally )
为 false ,则
a. 让 thenFinally 为 onFinally 。
b. 让 catchFinally 为 onFinally 。
6. 否则,
a. 让 thenFinallyClosure 为一个新的 Abstract Closure ,其参数为
(value ),并捕获 onFinally 和 C ,当调用时执行以下步骤:
i. 让 result 为 ? Call (onFinally ,
undefined ).
ii. 让 p 为 ? PromiseResolve (C , result ).
iii. 让 returnValue 为一个新的 Abstract Closure
,其参数为空,捕获 value 并在调用时执行以下步骤:
1. 返回 value 。
iv. 让 valueThunk 为 CreateBuiltinFunction (returnValue ,
0, "" , « »).
v. 返回 ? Invoke (p , "then" , «
valueThunk »).
b. 让 thenFinally 为 CreateBuiltinFunction (thenFinallyClosure ,
1, "" , « »).
c. 让 catchFinallyClosure 为一个新的 Abstract Closure ,其参数为
(reason ),并捕获 onFinally 和 C ,当调用时执行以下步骤:
i. 让 result 为 ? Call (onFinally ,
undefined ).
ii. 让 p 为 ? PromiseResolve (C , result ).
iii. 让 throwReason 为一个新的 Abstract Closure
,其参数为空,捕获 reason 并在调用时执行以下步骤:
1. 返回 ThrowCompletion (reason ).
iv. 让 thrower 为 CreateBuiltinFunction (throwReason ,
0, "" , « »).
v. 返回 ? Invoke (p , "then" , «
thrower »).
d. 让 catchFinally 为 CreateBuiltinFunction (catchFinallyClosure ,
1, "" , « »).
7. 返回 ? Invoke (promise , "then" , «
thenFinally , catchFinally »).
27.2.5.4 Promise.prototype.then ( onFulfilled ,
onRejected )
该方法在调用时执行以下步骤:
1. 让 promise 为 this 值。
2. 如果 IsPromise (promise ) 为
false ,则抛出 TypeError 异常。
3. 让 C 为 ? SpeciesConstructor (promise , %Promise% )。
4. 让 resultCapability 为 ? NewPromiseCapability (C )。
5. 返回 PerformPromiseThen (promise ,
onFulfilled , onRejected , resultCapability )。
27.2.5.4.1 PerformPromiseThen ( promise ,
onFulfilled , onRejected [ , resultCapability ] )
抽象操作 PerformPromiseThen 接受参数 promise (一个 Promise)、onFulfilled (一个 ECMAScript 语言值 )和
onRejected (一个 ECMAScript
语言值 )以及可选参数 resultCapability (一个 PromiseCapability
Record ),并返回一个 ECMAScript 语言值 。它对
promise 执行 “then” 操作,使用 onFulfilled 和 onRejected 作为其解决操作。如果传递了
resultCapability ,结果会通过更新 resultCapability 的 promise 来存储。如果没有传递,则
PerformPromiseThen 是由规范内部操作调用的,其结果并不重要。它在调用时执行以下步骤:
1. Assert : IsPromise (promise ) 为
true 。
2. 如果 resultCapability 不存在,则
a. 将 resultCapability 设置为
undefined 。
3. 如果 IsCallable (onFulfilled )
为 false ,则
a. 让 onFulfilledJobCallback 为
empty 。
4. 否则,
a. 让 onFulfilledJobCallback 为 HostMakeJobCallback (onFulfilled )。
5. 如果 IsCallable (onRejected )
为 false ,则
a. 让 onRejectedJobCallback 为
empty 。
6. 否则,
a. 让 onRejectedJobCallback 为 HostMakeJobCallback (onRejected )。
7. 让 fulfillReaction 为 PromiseReaction
Record { [[Capability]] : resultCapability ,
[[Type]] : fulfill , [[Handler]] : onFulfilledJobCallback }。
8. 让 rejectReaction 为 PromiseReaction
Record { [[Capability]] : resultCapability ,
[[Type]] : reject , [[Handler]] : onRejectedJobCallback }。
9. 如果 promise .[[PromiseState]]
为 pending ,则
a. 将 fulfillReaction 添加到 promise .[[PromiseFulfillReactions]] 中。
b. 将 rejectReaction 添加到 promise .[[PromiseRejectReactions]] 中。
10. 否则,如果 promise .[[PromiseState]] 为 fulfilled ,则
a. 让 value 为 promise .[[PromiseResult]] 。
b. 让 fulfillJob 为 NewPromiseReactionJob (fulfillReaction ,
value )。
c. 执行 HostEnqueuePromiseJob (fulfillJob .[[Job]] , fulfillJob .[[Realm]] )。
11. 否则,
a. Assert : promise .[[PromiseState]] 的值为 rejected 。
b. 让 reason 为 promise .[[PromiseResult]] 。
c. 如果 promise .[[PromiseIsHandled]] 为 false ,执行 HostPromiseRejectionTracker (promise ,
"handle" )。
d. 让 rejectJob 为 NewPromiseReactionJob (rejectReaction ,
reason )。
e. 执行 HostEnqueuePromiseJob (rejectJob .[[Job]] , rejectJob .[[Realm]] )。
12. 将 promise .[[PromiseIsHandled]] 设置为 true 。
13. 如果 resultCapability 为
undefined ,则
a. 返回 undefined 。
14. 否则,
a. 返回 resultCapability .[[Promise]] 。
27.2.5.5 Promise.prototype [ @@toStringTag ]
@@toStringTag 属性的初始值为字符串
"Promise" 。
该属性具有以下属性:{ [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
true }。
27.2.6 Promise 实例的属性
Promise 实例是 普通对象 ,从 Promise
原型对象 (即内建的 %Promise.prototype% )继承属性。
Promise 实例最初是以 表 87
中描述的内部槽创建的。
表 87: Promise 实例的内部槽
内部槽
类型
描述
[[PromiseState]]
pending 、fulfilled 或
rejected
决定 Promise 如何响应对其 then
方法的调用。
[[PromiseResult]]
一个 ECMAScript 语言值
Promise 被履行或拒绝的值(如果有的话)。仅在 [[PromiseState]] 不是
pending 时有意义。
[[PromiseFulfillReactions]]
一个 列表
的 PromiseReaction
记录
当 Promise 从 pending 状态转变为 fulfilled 状态时,要处理的
记录 。
[[PromiseRejectReactions]]
一个 列表
的 PromiseReaction
记录
当 Promise 从 pending 状态转变为 rejected 状态时,要处理的
记录 。
[[PromiseIsHandled]]
一个布尔值
表示 Promise 是否曾经有过履行或拒绝处理程序;用于未处理拒绝的追踪。
27.3 GeneratorFunction 对象
GeneratorFunctions 是通常通过评估 GeneratorDeclaration 、GeneratorExpression 和
GeneratorMethod
创建的函数。它们也可以通过调用
%GeneratorFunction%
内建对象创建。
图 6(仅供参考):生成器对象关系
27.3.1 GeneratorFunction 构造函数
GeneratorFunction 构造函数 :
是 %GeneratorFunction% 。
是 Function
的子类。
在作为函数调用而不是作为 构造函数 时,创建并初始化一个新的
GeneratorFunction。因此,函数调用 GeneratorFunction (…)
等同于对象创建表达式
new GeneratorFunction (…)
,并使用相同的参数。
可以作为类定义中 extends
子句的值。意图继承指定的 GeneratorFunction 行为的子类 构造函数 必须包含一个对
GeneratorFunction 构造函数 的 super
调用,以创建并初始化子类实例,并为内建的 GeneratorFunction 行为提供必要的内部槽。所有 ECMAScript 语法形式用于定义生成器 函数对象 都会直接创建 GeneratorFunction
的实例。没有语法手段可以创建 GeneratorFunction 子类的实例。
27.3.1.1 GeneratorFunction ( ...parameterArgs ,
bodyArg
)
最后一个参数(如果有的话)指定生成器函数的主体(可执行代码);任何前面的参数指定正式参数。
此函数在调用时执行以下步骤:
1. 让 C 为 活动函数对象 。
2. 如果 bodyArg 不存在,将 bodyArg
设置为空字符串。
3. 返回 ? 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
的初始值是Generator
原型对象 。
该属性具有 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
true } 的特性。
27.3.3.3 GeneratorFunction.prototype [ @@toStringTag ]
@@toStringTag 属性的初始值是字符串值"GeneratorFunction" 。
该属性具有 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
true } 的特性。
27.3.4 GeneratorFunction 实例
每个 GeneratorFunction 实例都是一个 ECMAScript 函数对象 ,并且具有表30 中列出的内部槽。这些实例的[[IsClassConstructor]] 内部槽的值都是false 。
每个 GeneratorFunction 实例都有以下自有属性:
27.3.4.1 length
"length" 属性的规范在20.2.4.1 中给出,也适用于
GeneratorFunction 实例。
27.3.4.2 name
"name" 属性的规范在20.2.4.2 中给出,也适用于
GeneratorFunction 实例。
27.3.4.3 prototype
每当创建一个 GeneratorFunction 实例时,另一个普通对象 也会被创建,并作为生成器函数的"prototype" 属性的初始值。该属性的值用于在使用[[Call]] 调用生成器函数对象 时初始化新创建的生成器的[[Prototype]] 内部槽。
该属性具有 { [[Writable]] : true , [[Enumerable]] : false , [[Configurable]] :
false } 的特性。
注
与 Function 实例不同,作为 GeneratorFunction 的"prototype" 属性值的对象没有一个值为 GeneratorFunction
实例的"constructor" 属性。
27.4 AsyncGeneratorFunction 对象
AsyncGeneratorFunctions 是通常通过计算AsyncGeneratorDeclaration 、AsyncGeneratorExpression 和AsyncGeneratorMethod 语法产生的函数。它们也可以通过调用%AsyncGeneratorFunction% 本征对象来创建。
27.4.1 AsyncGeneratorFunction 构造函数
AsyncGeneratorFunction 构造函数 :
是%AsyncGeneratorFunction% 。
是Function
的子类。
在作为函数调用而不是作为构造函数 调用时,创建并初始化一个新的
AsyncGeneratorFunction。因此,函数调用AsyncGeneratorFunction (...)
等同于对象创建表达式new AsyncGeneratorFunction (...)
,并带有相同的参数。
可以用作类定义的extends
子句的值。意图继承指定 AsyncGeneratorFunction 行为的子类构造函数 必须包含对
AsyncGeneratorFunction 构造函数 的super
调用,以使用内建
AsyncGeneratorFunction 行为所需的内部槽创建和初始化子类实例。所有 ECMAScript 定义异步生成器函数对象 的语法形式都直接创建
AsyncGeneratorFunction 的实例。没有语法手段创建 AsyncGeneratorFunction 子类的实例。
27.4.1.1 AsyncGeneratorFunction ( ...parameterArgs ,
bodyArg )
最后一个参数(如果有的话)指定异步生成器函数的主体(可执行代码);之前的任何参数指定形式参数。
此函数在调用时执行以下步骤:
1. 令C 为活动函数对象 。
2. 如果bodyArg 不存在,则将bodyArg 设置为空字符串。
3. 返回 ? 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
的初始值是AsyncGenerator
原型对象 。
该属性具有 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
true } 的特性。
27.4.3.3 AsyncGeneratorFunction.prototype [ @@toStringTag ]
@@toStringTag 属性的初始值是字符串值"AsyncGeneratorFunction" 。
该属性具有 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
true } 的特性。
27.4.4 AsyncGeneratorFunction 实例
每个 AsyncGeneratorFunction 实例都是一个 ECMAScript 函数对象 ,并且具有表30 中列出的内部槽。这些实例的[[IsClassConstructor]] 内部槽的值都是false 。
每个 AsyncGeneratorFunction 实例都有以下自有属性:
27.4.4.1 length
"length" 属性的值是一个整数 ,表示 AsyncGeneratorFunction
预期的典型参数数量。但是,语言允许用其他数量的参数调用该函数。调用参数数量与其"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" 属性的初始值。该属性的值用于在使用[[Call]] 调用生成器函数对象 时初始化新创建的异步生成器的[[Prototype]] 内部槽。
该属性具有 { [[Writable]] : true , [[Enumerable]] : false , [[Configurable]] :
false } 的特性。
注
与函数实例不同,作为 AsyncGeneratorFunction 的"prototype" 属性值的对象没有一个值为
AsyncGeneratorFunction 实例的"constructor" 属性。
27.5 Generator 对象
Generator 是生成器函数的实例,并符合Iterator 和Iterable 接口。
Generator 实例直接从创建该实例的 Generator 函数的"prototype" 属性的初始值对象继承属性。Generator 实例间接从 Generator
Prototype 内置对象%GeneratorFunction.prototype.prototype% 继承属性。
27.5.1 Generator 原型对象的属性
Generator 原型对象 :
是%GeneratorFunction.prototype.prototype% 。
是一个普通对象 。
不是 Generator 实例,并且没有[[GeneratorState]] 内部槽。
有一个[[Prototype]] 内部槽,其值为%IteratorPrototype% 。
具有所有 Generator 实例间接继承的属性。
27.5.1.1 Generator.prototype.constructor
Generator.prototype.constructor
的初始值是%GeneratorFunction.prototype% 。
该属性具有 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
true } 的特性。
27.5.1.2 Generator.prototype.next ( value )
1. 返回 ? GeneratorResume (this 值, value ,
empty )。
27.5.1.3 Generator.prototype.return ( value )
此方法在调用时执行以下步骤:
1. 令g 为this 值。
2. 令C 为完成记录 {
[[Type]] : return , [[Value]] :
value , [[Target]] :
empty }。
3. 返回 ? GeneratorResumeAbrupt (g , C ,
empty )。
27.5.1.4 Generator.prototype.throw ( exception )
此方法在调用时执行以下步骤:
1. 令g 为this 值。
2. 令C 为ThrowCompletion (exception )。
3. 返回 ? GeneratorResumeAbrupt (g , C ,
empty )。
27.5.1.5 Generator.prototype [ @@toStringTag ]
@@toStringTag 属性的初始值是字符串值"Generator" 。
该属性具有 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
true } 的特性。
27.5.2 Generator 实例的属性
Generator 实例最初创建时具有表88 中描述的内部槽。
表88:Generator 实例的内部槽
内部槽
类型
描述
[[GeneratorState]]
undefined , suspended-start ,
suspended-yield , executing , 或
completed
< td>
生成器的当前执行状态。
[[GeneratorContext]]
一个执行上下文
执行此生成器代码时使用的执行上下文 。
[[GeneratorBrand]]
一个字符串或empty
用于区分不同类型生成器的标记。ECMAScript 源文本 声明的生成器的[[GeneratorBrand]] 始终为empty 。
27.5.3 Generator 抽象操作
27.5.3.1 GeneratorStart ( generator , generatorBody )
抽象操作 GeneratorStart 接受参数 generator (一个 Generator)和 generatorBody (一个函数主体 解析节点 或没有参数的抽象闭包 ),并返回unused 。调用时执行以下步骤:
1. 断言 :generator 的[[GeneratorState]] 的值为undefined 。
2. 令genContext 为运行执行上下文 。
3. 将genContext 的 Generator 组件设置为generator 。
4. 令closure 为一个新的抽象闭包 ,没有参数,捕获generatorBody ,并在调用时执行以下步骤:
a. 令acGenContext 为运行执行上下文 。
b. 令acGenerator 为acGenContext 的 Generator
组件。
c. 如果generatorBody 是一个解析节点 ,则
i. 令result 为完成 (评估 generatorBody )。
d. 否则,
i. 断言 :generatorBody 是一个没有参数的抽象闭包 。
ii. 令result 为generatorBody ()。
e. 断言 :如果我们在此返回,则生成器要么抛出异常,要么执行隐式或显式返回。
f. 从执行上下文栈 中移除acGenContext ,并将位于执行上下文栈 顶部的执行上下文 恢复为运行执行上下文 。
g. 将acGenerator 的[[GeneratorState]] 设置为completed 。
h.
注意:一旦生成器进入completed 状态,就永远不会离开它,并且其关联的执行上下文 永远不会恢复。在这一点上,可以丢弃与acGenerator 相关的任何执行状态。
i. 如果result 是正常完成 ,则
i. 令resultValue 为undefined 。
j. 否则,如果result 是返回完成 ,则
i. 令resultValue 为result 的[[Value]] 。
k. 否则,
i. 断言 :result 是抛出完成 。
ii. 返回 ? result 。
l. 返回CreateIterResultObject (resultValue ,
true )。
5. 设置genContext 的代码评估状态,以便在恢复该执行上下文 的评估时,将调用closure ,没有参数。
6. 将generator 的[[GeneratorContext]] 设置为genContext 。
7. 将generator 的[[GeneratorState]] 设置为suspended-start 。
8. 返回unused 。
27.5.3.2 GeneratorValidate ( generator ,
generatorBrand )
抽象操作 GeneratorValidate 接受参数 generator (一个ECMAScript
语言值 )和generatorBrand (一个字符串或empty ),并返回正常完成,包含 suspended-start 、suspended-yield 或completed 之一,或抛出完成 。调用时执行以下步骤:
1. 执行 ? RequireInternalSlot (generator ,
[[GeneratorState]] )。
2. 执行 ? RequireInternalSlot (generator ,
[[GeneratorBrand]] )。
3. 如果generator 的[[GeneratorBrand]] 不是generatorBrand ,则抛出一个TypeError 异常。
4. 断言 :generator 也有一个[[GeneratorContext]] 内部槽。
5. 令state 为generator 的[[GeneratorState]] 。
6.
如果state 是executing ,则抛出一个TypeError 异常。
7. 返回state 。
27.5.3.3 GeneratorResume ( generator , value ,
generatorBrand )
抽象操作 GeneratorResume 接受参数 generator (一个ECMAScript
语言值 )、value (一个ECMAScript
语言值 或empty )和generatorBrand (一个字符串或empty ),并返回正常完成,包含 一个ECMAScript
语言值 或抛出完成 。调用时执行以下步骤:
1. 令state 为 ? GeneratorValidate (generator ,
generatorBrand )。
2.
如果state 是completed ,则返回CreateIterResultObject (undefined ,
true )。
3. 断言 :state 要么是suspended-start ,要么是suspended-yield 。
4. 令genContext 为generator 的[[GeneratorContext]] 。
5. 令methodContext 为运行执行上下文 。
6. 暂停methodContext 。
7. 将generator 的[[GeneratorState]] 设置为executing 。
8. 将genContext 推送到执行上下文栈 中;genContext 现在是运行执行上下文 。
9. 恢复暂停评估genContext ,使用NormalCompletion (value )作为暂停操作的结果。令result 为恢复计算返回的值。
10. 断言 :当我们返回这里时,genContext 已经从执行上下文栈 中移除,并且methodContext 是当前运行执行上下文 。
11. 返回 ? result 。
27.5.3.4 GeneratorResumeAbrupt ( generator ,
abruptCompletion , generatorBrand )
抽象操作 GeneratorResumeAbrupt 接受参数 generator (一个ECMAScript
语言值 )、abruptCompletion (一个返回完成 或抛出完成 ),并返回一个正常完成,包含 一个ECMAScript
语言值 或抛出完成 。调用时执行以下步骤:
1. 令state 为 ? GeneratorValidate (generator ,
generatorBrand )。
2. 如果state 是suspended-start ,则
a. 将generator 的[[GeneratorState]] 设置为completed 。
b.
注意:一旦生成器进入completed 状态,就永远不会离开它,并且其关联的执行上下文 永远不会恢复。在这一点上,可以丢弃与generator 相关的任何执行状态。
c. 将state 设置为completed 。
3. 如果state 是completed ,则
a. 如果abruptCompletion 是返回完成 ,则
i. 返回CreateIterResultObject (abruptCompletion 的[[Value]] , true )。
b. 返回 ? abruptCompletion 。
4. 断言
:state 是suspended-yield 。
5. 令genContext 为generator 的[[GeneratorContext]] 。
6. 令methodContext 为运行执行上下文 。
7. 暂停methodContext 。
8. 将generator 的[[GeneratorState]] 设置为executing 。
9. 将genContext 推送到执行上下文栈 中;genContext 现在是运行执行上下文 。
10. 恢复暂停评估genContext ,使用abruptCompletion 作为暂停操作的结果。令result 为恢复计算返回的完成记录 。
11. 断言 :当我们返回这里时,genContext 已经从执行上下文栈 中移除,并且methodContext 是当前运行执行上下文 。
12. 返回 ? result 。
27.5.3.5 GetGeneratorKind ( )
抽象操作 GetGeneratorKind
不接受参数,并返回non-generator 、sync 或async 。调用时执行以下步骤:
1. 令genContext 为运行执行上下文 。
2. 如果genContext 没有 Generator
组件,则返回non-generator 。
3. 令generator 为genContext 的 Generator 组件。
4. 如果generator 有一个[[AsyncGeneratorState]] 内部槽,则返回async 。
5. 否则,返回sync 。
27.5.3.6 GeneratorYield ( iterNextObj )
抽象操作 GeneratorYield 接受参数 iterNextObj (一个符合IteratorResult 接口的对象),并返回正常完成,包含 一个ECMAScript
语言值 或抛出完成 。调用时执行以下步骤:
1. 令genContext 为运行执行上下文 。
2. 断言 :genContext 是一个生成器的执行上下文 。
3. 令generator 为genContext 的 Generator 组件的值。
4. 断言 :GetGeneratorKind ()
是sync 。
5. 将generator 的[[GeneratorState]] 设置为suspended-yield 。
6. 从执行上下文栈 中移除genContext ,并将位于执行上下文栈 顶部的执行上下文 恢复为运行执行上下文 。
7. 令callerContext 为运行执行上下文 。
8. 恢复callerContext ,传递NormalCompletion (iterNextObj )。如果genContext 再次恢复,则令resumptionValue 为恢复的完成记录 。
9. 断言 :如果控制到达这里,那么genContext 再次成为运行执行上下文 。
10. 返回resumptionValue 。
27.5.3.7 Yield ( value )
抽象操作 Yield 接受参数 value (一个ECMAScript
语言值 ),并返回正常完成,包含 一个ECMAScript
语言值 或抛出完成 。调用时执行以下步骤:
1. 令generatorKind 为GetGeneratorKind ()。
2. 如果generatorKind 是async ,则返回
? AsyncGeneratorYield (? Await (value ))。
3. 否则,返回 ? GeneratorYield (CreateIterResultObject (value ,
false ))。
27.5.3.8 CreateIteratorFromClosure ( closure ,
generatorBrand , generatorPrototype )
抽象操作 CreateIteratorFromClosure 接受参数 closure (一个没有参数的抽象闭包 )、generatorBrand (一个字符串或empty )和generatorPrototype (一个对象),并返回一个
Generator。调用时执行以下步骤:
1. 注意:closure 可以包含Yield 操作的使用,以生成一个
IteratorResult 对象。
2. 令internalSlotsList 为« [[GeneratorState]] , [[GeneratorContext]] , [[GeneratorBrand]] »。
3. 令generator 为OrdinaryObjectCreate (generatorPrototype ,
internalSlotsList )。
4. 将generator 的[[GeneratorBrand]] 设置为generatorBrand 。
5. 将generator 的[[GeneratorState]] 设置为undefined 。
6. 令callerContext 为运行执行上下文 。
7. 令calleeContext 为一个新的执行上下文 。
8. 将calleeContext 的函数设置为null 。
9. 将calleeContext 的领域 设置为当前领域记录 。
10. 将calleeContext 的 ScriptOrModule
设置为callerContext 的 ScriptOrModule。
11. 如果callerContext 尚未暂停,则暂停callerContext 。
12. 将calleeContext 推送到执行上下文栈 中;calleeContext 现在是运行执行上下文 。
13. 执行GeneratorStart (generator ,
closure )。
14. 从执行上下文栈 中移除calleeContext ,并将callerContext 恢复为运行执行上下文 。
15. 返回generator 。
27.6 AsyncGenerator Objects
AsyncGenerator是异步生成器函数的实例,符合AsyncIterator和AsyncIterable接口。
AsyncGenerator实例直接从创建该实例的AsyncGenerator函数的"prototype" 属性的初始值对象继承属性。AsyncGenerator实例间接从AsyncGenerator
Prototype内置对象继承属性,%AsyncGeneratorFunction.prototype.prototype% 。
27.6.1 Properties of the AsyncGenerator Prototype Object
AsyncGenerator prototype object 的属性:
是%AsyncGeneratorFunction.prototype.prototype% 。
是一个普通对象 。
不是AsyncGenerator实例,没有[[AsyncGeneratorState]] 内部槽。
有一个[[Prototype]] 内部槽,其值为%AsyncIteratorPrototype% 。
具有所有AsyncGenerator实例间接继承的属性。
27.6.1.1 AsyncGenerator.prototype.constructor
AsyncGenerator.prototype.constructor的初始值是%AsyncGeneratorFunction.prototype% 。
这个属性的属性是 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
true }。
27.6.1.2 AsyncGenerator.prototype.next ( value )
1. 令generator 为this 值。
2. 令promiseCapability 为 ! NewPromiseCapability (%Promise% )。
3. 令result 为Completion (AsyncGeneratorValidate (generator ,
empty ))。
4. IfAbruptRejectPromise (result ,
promiseCapability )。
5. 令state 为generator 的[[AsyncGeneratorState]] 。
6. 如果state 是completed ,则
a. 令iteratorResult 为CreateIterResultObject (undefined ,
true )。
b. 执行 ! Call (promiseCapability 的[[Resolve]] ,undefined ,«
iteratorResult »)。
c. 返回promiseCapability 的[[Promise]] 。
7. 令completion 为NormalCompletion (value )。
8. 执行AsyncGeneratorEnqueue (generator ,
completion , promiseCapability )。
9.
如果state 是suspended-start 或suspended-yield ,则
a. 执行AsyncGeneratorResume (generator ,
completion )。
10. 否则,
a. 断言 :
state 是executing 或awaiting-return 。
11. 返回promiseCapability 的[[Promise]] 。
27.6.1.3 AsyncGenerator.prototype.return ( value )
1. 令generator 为this 值。
2. 令promiseCapability 为 ! NewPromiseCapability (%Promise% )。
3. 令result 为Completion (AsyncGeneratorValidate (generator ,
empty ))。
4. IfAbruptRejectPromise (result ,
promiseCapability )。
5. 令completion 为Completion
Record { [[Type]] : return , [[Value]] : value , [[Target]] :
empty }。
6. 执行AsyncGeneratorEnqueue (generator ,
completion , promiseCapability )。
7. 令state 为generator 的[[AsyncGeneratorState]] 。
8.
如果state 是suspended-start 或completed ,则
a. 将generator 的[[AsyncGeneratorState]] 设置为awaiting-return 。
b. 执行 ! AsyncGeneratorAwaitReturn (generator )。
9. 否则如果state 是suspended-yield ,则
a. 执行AsyncGeneratorResume (generator ,
completion )。
10. 否则,
a. 断言 :
state 是executing 或awaiting-return 。
11. 返回promiseCapability 的[[Promise]] 。
27.6.1.4 AsyncGenerator.prototype.throw ( exception )
1. 令generator 为this 值。
2. 令promiseCapability 为 ! NewPromiseCapability (%Promise% )。
3. 令result 为Completion (AsyncGeneratorValidate (generator ,
empty ))。
4. IfAbruptRejectPromise (result ,
promiseCapability )。
5. 令state 为generator 的[[AsyncGeneratorState]] 。
6. 如果state 是suspended-start ,则
a. 将generator 的[[AsyncGeneratorState]] 设置为completed 。
b. 将state 设置为completed 。
7. 如果state 是completed ,则
a. 执行 ! Call (promiseCapability 的[[Reject]] ,undefined ,« exception »)。
b. 返回promiseCapability 的[[Promise]] 。
8. 令completion 为ThrowCompletion (exception )。
9. 执行AsyncGeneratorEnqueue (generator ,
completion , promiseCapability )。
10. 如果state 是suspended-yield ,则
a. 执行AsyncGeneratorResume (generator ,
completion )。
11. 否则,
a. 断言 :
state 是executing 或awaiting-return 。
12. 返回promiseCapability 的[[Promise]] 。
27.6.1.5 AsyncGenerator.prototype [ @@toStringTag ]
AsyncGenerator.prototype的@@toStringTag 属性的初始值是字符串值"AsyncGenerator" 。
这个属性的属性是 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
true }。
27.6.2 AsyncGenerator 实例的属性
AsyncGenerator 实例最初创建时具有以下描述的内部插槽:
表 89: AsyncGenerator 实例的内部插槽
内部插槽
类型
描述
[[AsyncGeneratorState]]
undefined , suspended-start ,
suspended-yield , executing ,
awaiting-return , 或 completed
异步生成器的当前执行状态。
[[AsyncGeneratorContext]]
一个执行上下文
用于执行此异步生成器代码的执行上下文 。
[[AsyncGeneratorQueue]]
一个列表 ,包含AsyncGeneratorRequest 记录
记录 ,表示恢复异步生成器的请求。除状态转换期间外,只有当[[AsyncGeneratorState]] 为executing 或awaiting-return 时,它才是非空的。
[[GeneratorBrand]]
一个字符串或empty
用于区分不同类型异步生成器的品牌。由ECMAScript 源代码 声明的异步生成器的[[GeneratorBrand]] 总是empty 。
27.6.3 AsyncGenerator 抽象操作
27.6.3.1 AsyncGeneratorRequest 记录
一个AsyncGeneratorRequest 是一个用于存储有关异步生成器应如何恢复的信息的记录 值,并包含完成或拒绝相应
Promise 的能力。
它们具有以下字段:
表 90: AsyncGeneratorRequest 记录 字段
27.6.3.2 AsyncGeneratorStart ( generator ,
generatorBody )
抽象操作 AsyncGeneratorStart 接受参数generator (一个 AsyncGenerator)和generatorBody (一个函数体 解析节点 或一个无参数的抽象闭包 ),并返回unused 。调用时执行以下步骤:
1. 断言 :generator .[[AsyncGeneratorState]] 是undefined 。
2. 让genContext 成为正在运行的执行上下文 。
3. 将genContext 的生成器组件设置为generator 。
4. 让closure 成为一个新的抽象闭包 ,无参数,捕获generatorBody ,并在调用时执行以下步骤:
a. 让acGenContext 成为正在运行的执行上下文 。
b. 让acGenerator 成为acGenContext 的生成器组件。
c. 如果generatorBody 是一个解析节点 ,则
i. 让result 成为完成 (评估 (generatorBody ))。
d. 否则,
i. 断言 :generatorBody 是一个无参数的抽象闭包 。
ii. 让result 成为完成 (generatorBody ())。
e. 断言 :如果我们在这里返回,异步生成器要么抛出了一个异常,要么执行了隐式或显式的返回。
f. 将acGenContext 从执行上下文堆栈 中移除,并将位于执行上下文堆栈 顶部的执行上下文 恢复为正在运行的执行上下文 。
g. 将acGenerator .[[AsyncGeneratorState]] 设置为completed 。
h. 如果result 是正常完成 ,则将result 设置为NormalCompletion (undefined )。
i. 如果result 是返回完成 ,则将result 设置为NormalCompletion (result .[[Value]] )。
j. 执行AsyncGeneratorCompleteStep (acGenerator ,
result , true )。
k. 执行AsyncGeneratorDrainQueue (acGenerator )。
l. 返回undefined 。
5. 设置genContext 的代码评估状态,以便当恢复该执行上下文 的评估时,将调用closure ,无参数。
6. 将generator .[[AsyncGeneratorContext]] 设置为genContext 。
7. 将generator .[[AsyncGeneratorState]] 设置为suspended-start 。
8. 将generator .[[AsyncGeneratorQueue]] 设置为一个新的空列表 。
9. 返回unused 。
27.6.3.3 AsyncGeneratorValidate ( generator ,
generatorBrand )
抽象操作 AsyncGeneratorValidate 接受参数generator (一个ECMAScript
语言值 )和generatorBrand (一个字符串或empty ),并返回一个包含 unused 的正常完成或一个抛出完成 。调用时执行以下步骤:
1. 执行? RequireInternalSlot (generator ,
[[AsyncGeneratorContext]] )。
2. 执行? RequireInternalSlot (generator ,
[[AsyncGeneratorState]] )。
3. 执行? RequireInternalSlot (generator ,
[[AsyncGeneratorQueue]] )。
4. 如果generator .[[GeneratorBrand]] 不是generatorBrand ,则抛出一个TypeError 异常。
5. 返回unused 。
27.6.3.4 AsyncGeneratorEnqueue ( generator ,
completion , promiseCapability )
抽象操作 AsyncGeneratorEnqueue 接受参数generator (一个 AsyncGenerator)、completion (一个完成记录 )和promiseCapability (一个PromiseCapability
记录 ),并返回unused 。调用时执行以下步骤:
1. 让request 成为AsyncGeneratorRequest
{ [[Completion]] : completion , [[Capability]] : promiseCapability }。
2. 将request 附加到generator .[[AsyncGeneratorQueue
]] 。
3. 返回unused 。
27.6.3.5 AsyncGeneratorCompleteStep ( generator ,
completion , done [ , realm ] )
抽象操作 AsyncGeneratorCompleteStep 接受参数generator (一个
AsyncGenerator)、completion (一个完成记录 )、done (一个布尔值)和可选参数realm (一个领域记录 ),并返回unused 。调用时执行以下步骤:
1. 断言 :generator .[[AsyncGeneratorQueue]] 不为空。
2. 让next 成为generator .[[AsyncGeneratorQueue]] 的第一个元素。
3. 将第一个元素从generator .[[AsyncGeneratorQueue]] 中移除。
4. 让promiseCapability 成为next .[[Capability]] 。
5. 让value 成为completion .[[Value]] 。
6. 如果completion 是抛出完成 ,则
a. 执行! 调用 (promiseCapability .[[Reject]] , undefined , « value »)。
7. 否则,
a. 断言 :completion 是一个正常完成 。
b. 如果realm 存在,则
i. 让oldRealm 成为正在运行的执行上下文 的领域 。
ii. 将正在运行的执行上下文 的领域 设置为realm 。
iii. 让iteratorResult 成为CreateIterResultObject (value ,
done )。
iv. 将正在运行的执行上下文 的领域 设置为oldRealm 。
c. 否则,
i. 让iteratorResult 成为CreateIterResultObject (value ,
done )。
d. 执行! 调用 (promiseCapability .[[Resolve]] , undefined , «
iteratorResult »)。
8. 返回unused 。
27.6.3.6 AsyncGeneratorResume ( generator , completion
)
抽象操作 AsyncGeneratorResume 接受参数generator (一个 AsyncGenerator)和completion (一个完成记录 ),并返回unused 。调用时执行以下步骤:
1. 断言 :generator .[[AsyncGeneratorState]] 为suspended-start 或suspended-yield 。
2. 让genContext 成为generator .[[AsyncGeneratorContext]] 。
3. 让callerContext 成为正在运行的执行上下文 。
4. 暂停callerContext 。
5. 将generator .[[AsyncGeneratorState]] 设置为executing 。
6. 将genContext 推入执行上下文堆栈 ;genContext 现在是正在运行的执行上下文 。
7. 恢复genContext 的挂起评估 ,使用completion 作为挂起操作的结果。让result 成为恢复计算返回的完成记录 。
8. 断言 :result 从不是中断完成 。
9. 断言 :当我们返回到这里时,genContext 已从执行上下文堆栈 中移除,并且callerContext 是当前正在运行的执行上下文 。
10. 返回unused 。
27.6.3.7 AsyncGeneratorUnwrapYieldResumption ( resumptionValue )
抽象操作 AsyncGeneratorUnwrapYieldResumption 接受参数resumptionValue (一个完成记录 ),并返回一个包含 一个ECMAScript
语言值 的正常完成或一个中断完成 。调用时执行以下步骤:
1. 如果resumptionValue 不是返回完成 ,则返回?
resumptionValue 。
2. 让awaited 成为完成 (等待 (resumptionValue .[[Value]] ))。
3. 如果awaited 是抛出完成 ,则返回?
awaited 。
4. 断言 :awaited 是正常完成 。
5. 返回完成记录 {
[[Type]] : return , [[Value]] :
awaited .[[Value]] , [[Target]] :
empty }。
27.6.3.8 AsyncGeneratorYield ( value )
抽象操作 AsyncGeneratorYield 接受参数value (一个ECMAScript
语言值 ),并返回一个包含 一个ECMAScript
语言值 的正常完成或一个中断完成 。调用时执行以下步骤:
1. 让genContext 成为
正在运行的执行上下文 。
2. 断言 :genContext 是一个生成器的执行上下文 。
3. 让generator 成为genContext 的生成器组件的值。
4. 断言 :GetGeneratorKind ()是async 。
5. 让completion 成为NormalCompletion (value )。
6. 断言 :执行上下文堆栈 至少有两个元素。
7. 让previousContext 成为执行上下文堆栈 的倒数第二个元素。
8. 让previousRealm 成为previousContext 的领域 。
9. 执行AsyncGeneratorCompleteStep (generator ,
completion , false , previousRealm )。
10. 让queue 成为generator .[[AsyncGeneratorQueue]] 。
11. 如果queue 不为空,则
a. 注意:执行继续而不挂起生成器。
b. 让toYield 成为queue 的第一个元素。
c. 让resumptionValue 成为完成 (toYield .[[Completion]] )。
d. 返回? AsyncGeneratorUnwrapYieldResumption (resumptionValue )。
12. 否则,
a. 将generator .[[AsyncGeneratorState]] 设置为suspended-yield 。
b. 将genContext 从执行上下文堆栈 中移除,并将位于执行上下文堆栈 顶部的执行上下文 恢复为正在运行的执行上下文 。
c. 让callerContext 成为正在运行的执行上下文 。
d.
恢复callerContext ,传递undefined 。如果genContext 再次恢复,则让resumptionValue 成为完成记录 ,它用于恢复genContext 。
e. 断言 :如果控制到达这里,则genContext 再次成为正在运行的执行上下文 。
f. 返回? AsyncGeneratorUnwrapYieldResumption (resumptionValue )。
27.6.3.9 AsyncGeneratorAwaitReturn ( generator )
抽象操作 AsyncGeneratorAwaitReturn 接受参数generator (一个 AsyncGenerator),并返回一个包含 unused 的正常完成或一个抛出完成 。调用时执行以下步骤:
1. 让queue 成为generator .[[AsyncGeneratorQueue]] 。
2. 断言 :queue 不为空。
3. 让next 成为queue 的第一个元素。
4. 让completion 成为完成 (next .[[Completion]] )。
5. 断言 :completion 是一个返回完成 。
6. 让promise 成为? PromiseResolve (%Promise% ,
completion .[[Value]] )。
7. 让fulfilledClosure 成为一个新的抽象闭包 ,参数为(value ),捕获generator ,并在调用时执行以下步骤:
a. 将generator .[[AsyncGeneratorState]] 设置为completed 。
b. 让result 成为NormalCompletion (value )。
c. 执行AsyncGeneratorCompleteStep (generator ,
result , true )。
d. 执行AsyncGeneratorDrainQueue (generator )。
e. 返回undefined 。
8. 让onFulfilled 成为CreateBuiltinFunction (fulfilledClosure ,
1, "" , « »)。
9. 让rejectedClosure 成为一个新的抽象闭包 ,参数为(reason ),捕获generator ,并在调用时执行以下步骤:
a. 将generator .[[AsyncGeneratorState]] 设置为completed 。
b. 让result 成为ThrowCompletion (reason )。
c. 执行AsyncGeneratorCompleteStep (generator ,
result , true )。
d. 执行AsyncGeneratorDrainQueue (generator )。
e. 返回undefined 。
10. 让onRejected 成为CreateBuiltinFunction (rejectedClosure ,
1, "" , « »)。
11. 执行PerformPromiseThen (promise ,
onFulfilled , onRejected )。
12. 返回unused 。
27.6.3.10 AsyncGeneratorDrainQueue ( generator )
抽象操作 AsyncGeneratorDrainQueue 接受参数generator (一个
AsyncGenerator),并返回unused 。它会排空生成器的 AsyncGeneratorQueue,直到遇到一个包含返回完成 的AsyncGeneratorRequest 。调用时执行以下步骤:
1. 断言 :generator .[[AsyncGeneratorState]] 为completed 。
2. 让queue 成为generator .[[AsyncGeneratorQueue]] 。
3. 如果queue 为空,返回unused 。
4. 让done 成为false 。
5. 重复,当done 为false 时,
a. 让next 成为queue 的第一个元素。
b. 让completion 成为完成 (next .[[Completion]] )。
c. 如果completion 是一个返回完成 ,则
i. 将generator .[[AsyncGeneratorState]] 设置为awaiting-return 。
ii. 执行! AsyncGeneratorAwaitReturn (generator )。
iii. 将done 设置为true 。
d. 否则,
i. 如果completion 是一个正常完成 ,则
1. 将completion 设置为NormalCompletion (undefined )。
ii. 执行AsyncGeneratorCompleteStep (generator ,
completion , true )。
iii.
如果queue 为空,则将done 设置为true 。
6. 返回unused 。
27.6.3.11 CreateAsyncIteratorFromClosure ( closure ,
generatorBrand , generatorPrototype )
抽象操作 CreateAsyncIteratorFromClosure 接受参数closure (一个无参数的抽象闭包 )、generatorBrand (一个字符串或empty )和generatorPrototype (一个对象),并返回一个
AsyncGenerator。调用时执行以下步骤:
1. 注意:closure 可以包含等待 操作的使用以及Yield 操作的使用,以生成一个 IteratorResult 对象。
2. 让internalSlotsList 成为« [[AsyncGeneratorState]] , [[AsyncGeneratorContext]] ,
[[AsyncGeneratorQueue]] , [[GeneratorBrand]] »。
3. 让generator 成为OrdinaryObjectCreate (generatorPrototype ,
internalSlotsList )。
4. 将generator .[[GeneratorBrand]] 设置为generatorBrand 。
5. 将generator .[[AsyncGeneratorState]] 设置为undefined 。
6. 让callerContext 成为正在运行的执行上下文 。
7. 让calleeContext 成为一个新的执行上下文 。
8. 将calleeContext 的函数设置为null 。
9. 将calleeContext 的领域 设置为当前领域记录 。
10. 将calleeContext 的 ScriptOrModule
设置为callerContext 的 ScriptOrModule。
11. 如果callerContext 尚未挂起,挂起callerContext 。
12. 将calleeContext 推入< emu-xref
href="#execution-context-stack" id="_ref_15211">执行上下文堆栈 ;calleeContext 现在是正在运行的执行上下文 。
13. 执行AsyncGeneratorStart (generator ,
closure )。
14. 将calleeContext 从执行上下文堆栈 中移除,并将callerContext 恢复为正在运行的执行上下文 。
15. 返回generator 。
27.7 异步函数对象
异步函数是通常通过求值 AsyncFunctionDeclaration 、AsyncFunctionExpression 、AsyncMethod 和 AsyncArrowFunction
创建的函数。它们也可以通过调用 %AsyncFunction% 内建函数来创建。
27.7.1 AsyncFunction 构造函数
AsyncFunction 构造函数 :
是 %AsyncFunction% 。
是 Function
的子类。
当作为函数调用而不是作为 构造函数 时,创建并初始化一个新的 AsyncFunction。因此,函数调用
AsyncFunction(…)
等同于使用相同参数的对象创建表达式 new AsyncFunction(…)
。
可以用作类定义的 extends
子句的值。打算继承指定的 AsyncFunction 行为的子类 构造函数 必须包含对 AsyncFunction
构造函数 的 super
调用,以创建和初始化一个具有内建异步函数行为所需内部插槽的子类实例。所有 ECMAScript 语法形式的异步 函数对象 创建 AsyncFunction
的直接实例。没有语法手段可以创建 AsyncFunction 子类的实例。
27.7.1.1 AsyncFunction ( …parameterArgs , bodyArg )
最后一个参数(如果有的话)指定异步函数的主体(可执行代码)。任何前面的参数指定正式参数。
调用该函数时,会执行以下步骤:
1. 让 C 为 活动函数对象 。
2. 如果 bodyArg 不存在,则将 bodyArg 设置为空字符串。
3. 返回 ? 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 [ @@toStringTag ]
@@toStringTag 属性的初始值是字符串值
"AsyncFunction" 。
此属性的特性为 { [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
true }。
27.7.4 AsyncFunction 实例
每个 AsyncFunction 实例都是 ECMAScript 函数对象 ,并且具有 表 30
中列出的内部插槽。所有此类实例的 [[IsClassConstructor]] 内部插槽的值为
false 。AsyncFunction 实例不是 构造函数 ,也没有 [[Construct]] 内部方法。由于 AsyncFunction 实例不可构造,因此没有原型属性。
每个 AsyncFunction 实例具有以下自身属性:
27.7.4.1 length
函数实例的 "length" 属性的规范在 20.2.4.1 中给出,该规范也适用于
AsyncFunction 实例。
27.7.4.2 name
函数实例的 "name" 属性的规范在 20.2.4.2 中给出,该规范也适用于
AsyncFunction 实例。
27.7.5 异步函数抽象操作
27.7.5.1 AsyncFunctionStart ( promiseCapability ,
asyncFunctionBody )
抽象操作 AsyncFunctionStart 接受参数 promiseCapability (一个 PromiseCapability
Record )和 asyncFunctionBody (一个 FunctionBody 解析节点 或一个 ExpressionBody
解析节点 ) 并返回
unused 。调用时执行以下步骤:
1. 让 runningContext 为 正在运行的执行上下文 。
2. 让 asyncContext 为 runningContext 的副本。
3. 注意:复制执行状态是必要的,以便 AsyncBlockStart
能够恢复其执行。恢复当前正在执行的上下文是不明确的。
4. 执行 AsyncBlockStart (promiseCapability ,
asyncFunctionBody , asyncContext )。
5. 返回 unused 。
27.7.5.2 AsyncBlockStart ( promiseCapability ,
asyncBody , asyncContext )
抽象操作 AsyncBlockStart 接受参数 promiseCapability (一个 PromiseCapability
Record )、asyncBody (一个 解析节点 ),
和 asyncContext (一个 执行上下文 )
并返回 unused 。调用时执行以下步骤:
1. 断言 :promiseCapability 是
一个 PromiseCapability
Record 。
2. 让 runningContext 为 正在运行的执行上下文 。
3. 让 closure 为一个新的 抽象闭包 ,没有参数,捕获
promiseCapability 和 asyncBody ,并在调用时执行以下步骤:
a. 让 acAsyncContext 为 正在运行的执行上下文 。
b. 让 result 为 Completion (对
asyncBody 的 求值 )。
c. 断言 :如果我们回到这里,异步函数要么抛出了异常,要么进行了隐式或显式返回;所有等待已完成。
d. 从 执行上下文栈 中移除
acAsyncContext ,并恢复位于 执行上下文栈 顶部的
执行上下文 为
正在运行的执行上下文 。
e. 如果 result 是一个 正常完成 ,则
i. 执行 ! Call (promiseCapability .[[Resolve]] , undefined , «
undefined »).
f. 否则,如果 result 是一个 返回完成 ,则
i. 执行 ! Call (promiseCapability .[[Resolve]] , undefined , « result .[[Value]] »).
g. 否则,
i. 断言 :result 是一个
抛出完成 。
ii. 执行 ! Call (promiseCapability .[[Reject]] , undefined , « result .[[Value]] »).
h. 返回
unused .
4. 设置 asyncContext 的代码求值状态,使得当对该
执行上下文 进行恢复时,
closure 将被调用且没有
参数。
5. 将 asyncContext 推送到 执行上下文栈 ;asyncContext
现在是
正在运行的执行上下文 。
6. 恢复 asyncContext
的挂起求值 。让 result 为恢复计算的返回值。
7. 断言 :当我们回到这里时,asyncContext 已经从
执行上下文栈
中移除,runningContext 是当前的
正在运行的执行上下文 。
8. 断言 :result 是一个
正常完成 ,其值为
unused 。该值的可能来源是 Await ,或者,如果异步函数没有等待任何东西,则为上述步骤
3.h 。
9. 返回 unused 。
27.7.5.3 Await ( value )
抽象操作 Await 接受参数 value (一个 ECMAScript 语言值 ),并返回一个
正常完成记录 ,其中包含一个
ECMAScript 语言值 或
empty ,或者一个 抛出完成记录 。调用时执行以下步骤:
1. 让 asyncContext 为 正在运行的执行上下文 。
2. 让 promise 为 ? PromiseResolve (%Promise% ,
value ).
3. 让 fulfilledClosure 为一个新的 抽象闭包 ,参数为 (v ),捕获
asyncContext ,并在调用时执行以下步骤:
a. 让 prevContext 为 正在运行的执行上下文 。
b. 挂起 prevContext 。
c. 将 asyncContext 推送到 执行上下文栈 ;asyncContext
现在是 正在运行的执行上下文 。
d. 恢复挂起的 asyncContext
的计算 ,使用 正常完成 (v )
作为使其挂起的操作的结果。
e. 断言 :当我们到达此步骤时,asyncContext
已经从 执行上下文栈
中移除,prevContext 是当前的 正在运行的执行上下文 。
f. 返回 undefined 。
4. 让 onFulfilled 为 CreateBuiltinFunction (fulfilledClosure ,1,"" ,« »)。
5. 让 rejectedClosure 为一个新的 抽象闭包 ,参数为
(reason ),捕获 asyncContext ,并在调用时执行以下步骤:
a. 让 prevContext 为 正在运行的执行上下文 。
b. 挂起 prevContext 。
c. 将 asyncContext 推送到 执行上下文栈 ;asyncContext
现在是 正在运行的执行上下文 。
d. 恢复挂起的 asyncContext
的计算 ,使用 抛出完成 (reason )
作为使其挂起的操作的结果。
e. 断言 :当我们到达此步骤时,asyncContext
已经从 执行上下文栈
中移除,prevContext 是当前的 正在运行的执行
上下文 。
f. 返回 undefined 。
6. 让 onRejected 为 CreateBuiltinFunction (rejectedClosure ,1,"" ,« »)。
7. 执行 PerformPromiseThen (promise ,
onFulfilled ,onRejected )。
8. 从 执行上下文栈 中移除
asyncContext ,并将位于 执行上下文 栈顶部的上下文恢复为 正在运行的执行上下文 。
9. 让 callerContext 为 正在运行的执行上下文 。
10. 恢复 callerContext ,传递 empty 。如果
asyncContext 再次恢复,则让 completion 为其恢复时使用的 完成记录 。
11. 断言 :如果控制到达此处,则 asyncContext 再次成为
正在运行的执行上下文 。
12. 返回 completion 。
28 反射
28.1 Reflect 对象
Reflect 对象:
是 %Reflect% 。
是 "Reflect" 属性的初始值,属于 全局对象 。
是一个 普通对象 。
有一个内部槽 [[Prototype]] ,其值是 %Object.prototype% 。
不是一个 函数对象 。
没有 [[Construct]] 内部方法;不能用 new
操作符作为一个 构造函数 。
没有 [[Call]] 内部方法;不能作为函数调用。
28.1.1 Reflect.apply ( target , thisArgument ,
argumentsList )
此函数在调用时执行以下步骤:
1. 如果 IsCallable (target ) 是
false ,则抛出 TypeError 异常。
2. 令 args 为 ? CreateListFromArrayLike (argumentsList )。
3. 执行 PrepareForTailCall ()。
4. 返回 ? Call (target ,
thisArgument ,
args )。
28.1.2 Reflect.construct ( target , argumentsList [ ,
newTarget ] )
此函数在调用时执行以下步骤:
1. 如果 IsConstructor (target ) 是
false ,则抛出 TypeError 异常。
2. 如果 newTarget 不存在,则将 newTarget 设为
target 。
3. 否则如果 IsConstructor (newTarget )
是 false ,则抛出 TypeError 异常。
4. 令 args 为 ? CreateListFromArrayLike (argumentsList )。
5. 返回 ? Construct (target , args ,
newTarget )。
28.1.3 Reflect.defineProperty ( target , propertyKey ,
attributes )
此函数在调用时执行以下步骤:
1. 如果 target 不是一个对象 ,则抛出
TypeError 异常。
2. 令 key 为 ? ToPropertyKey (propertyKey )。
3. 令 desc 为 ? ToPropertyDescriptor (attributes )。
4. 返回 ? target .[[DefineOwnProperty]] (key , desc )。
28.1.4 Reflect.deleteProperty ( target , propertyKey
)
此函数在调用时执行以下步骤:
1. 如果 target 不是一个对象 ,则抛出 TypeError 异常。
2. 令 key 为 ? ToPropertyKey (propertyKey )。
3. 返回 ? target .[[Delete]] (key )。
28.1.5 Reflect.get ( target , propertyKey [ ,
receiver ] )
此函数在调用时执行以下步骤:
1. 如果 target 不是一个对象 ,则抛出
TypeError 异常。
2. 令 key 为 ? ToPropertyKey (propertyKey )。
3. 如果 receiver 不存在,则
a. 将 receiver 设为 target 。
4. 返回 ? target .[[Get]] (key , receiver )。
28.1.6 Reflect.getOwnPropertyDescriptor ( target ,
propertyKey )
此函数在调用时执行以下步骤:
1. 如果 target 不是一个对象 ,则抛出
TypeError 异常。
2. 令 key 为 ? ToPropertyKey (propertyKey )。
3. 令 desc 为 ? target .[[GetOwnProperty]] (key )。
4. 返回 FromPropertyDescriptor (desc )。
28.1.7 Reflect.getPrototypeOf ( target )
此函数在调用时执行以下步骤:
1. 如果 target 不是一个对象 ,则抛出
TypeError 异常。
2. 返回 ? target .[[GetPrototypeOf]] () 。
28.1.8 Reflect.has ( target , propertyKey )
此函数在调用时执行以下步骤:
1. 如果 target 不是一个对象 ,则抛出
TypeError 异常。
2. 令 key 为 ? ToPropertyKey (propertyKey )。
3. 返回 ? target .[[HasProperty]] (key )。
28.1.9 Reflect.isExtensible ( target )
此函数在调用时执行以下步骤:
1. 如果 target 不是一个对象 ,则抛出
TypeError 异常。
2. 返回 ? target .[[IsExtensible]] () 。
28.1.10 Reflect.ownKeys ( target )
此函数在调用时执行以下步骤:
1. 如果 target 不是一个对象 ,则抛出
TypeError 异常
。
2. 令 keys 为 ? target .[[OwnPropertyKeys]] () 。
3. 返回 CreateArrayFromList (keys )。
28.1.11 Reflect.preventExtensions ( target )
此函数在调用时执行以下步骤:
1. 如果 target 不是一个对象 ,则抛出
TypeError 异常。
2. 返回 ? target .[[PreventExtensions]] () 。
28.1.12 Reflect.set ( target , propertyKey ,
V
[ , receiver ] )
此函数在调用时执行以下步骤:
1. 如果 target 不是一个对象 ,则抛出
TypeError 异常。
2. 令 key 为 ? ToPropertyKey (propertyKey )。
3. 如果 receiver 不存在,则
a. 将 receiver 设为 target 。
4. 返回 ? target .[[Set]] (key , V , receiver )。
28.1.13 Reflect.setPrototypeOf ( target , proto )
此函数在调用时执行以下步骤:
1. 如果 target 不是一个对象 ,则抛出
TypeError 异常。
2. 如果 proto 不是一个对象 且
proto 不是 null ,则抛出 TypeError 异常。
3. 返回 ? target .[[SetPrototypeOf]] (proto )。
28.1.14 Reflect [ @@toStringTag ]
@@toStringTag 属性的初始值是字符串值
"Reflect" 。
此属性具有 { [[Writable]] : false ,
[[Enumerable]] : false , [[Configurable]] :
true } 的属性。
28.2 代理对象
28.2.1 Proxy 构造函数
Proxy 构造函数 :
是 %Proxy% 。
是 "Proxy" 属性的初始值,该属性属于 全局对象 。
作为 构造函数 被调用时,创建并初始化一个新的 Proxy 对象。
不打算作为函数调用,若以此方式调用会抛出异常。
28.2.1.1 Proxy ( target , handler )
调用此函数时执行以下步骤:
1. 如果 NewTarget 为 undefined ,抛出
TypeError 异常。
2. 返回 ? ProxyCreate (target ,
handler )。
28.2.2 Proxy 构造函数的属性
Proxy 构造函数 :
具有一个 [[Prototype]] 内部插槽,其值为 %Function.prototype% 。
没有 "prototype" 属性,因为 Proxy 对象没有需要初始化的 [[Prototype]] 内部插槽。
具有以下属性:
28.2.2.1 Proxy.revocable ( target , handler )
此函数创建一个可撤销的 Proxy 对象。
调用此函数时执行以下步骤:
1. 让 proxy 为 ? ProxyCreate (target ,
handler )。
2. 让 revokerClosure 为一个新的 抽象闭包 ,没有参数,不捕获任何内容,当调用时执行以下步骤:
a. 让 F 为 活动函数对象 。
b. 让 p 为 F .[[RevocableProxy]] 。
c. 如果 p 为 null ,返回
undefined 。
d. 将 F .[[RevocableProxy]]
设置为 null 。
e. 断言 :p 是一个 Proxy 异域对象 。
f. 将 p .[[ProxyTarget]] 设置为
null 。
g. 将 p .[[ProxyHandler]] 设置为
null 。
h. 返回 undefined 。
3. 让 revoker 为 CreateBuiltinFunction (revokerClosure ,
0, "" , « [[RevocableProxy]] »)。
4. 将 revoker .[[RevocableProxy]]
设置为 proxy 。
5. 让 result 为 OrdinaryObjectCreate (%Object.prototype% )。
6. 执行 ! CreateDataPropertyOrThrow (result ,
"proxy" , proxy )。
7. 执行 ! CreateDataPropertyOrThrow (result ,
"revoke" , revoker )。
8. 返回 result 。
28.3 模块命名空间对象
模块命名空间对象是一个 模块命名空间异域对象 ,提供对模块导出绑定的基于属性的运行时访问。模块命名空间对象没有
构造函数 。相反,这样的对象是为每个被 ImportDeclaration 导入的模块创建的,该导入包含一个
NameSpaceImport 。
除了在 10.4.6
中指定的属性外,每个模块命名空间对象还具有以下自有属性:
28.3.1 @@toStringTag
@@toStringTag 属性的初始值是字符串值
"Module" 。
该属性具有以下属性:{ [[Writable]] : false , [[Enumerable]] : false , [[Configurable]] :
false }。
29 内存模型
内存一致性模型,或称为内存模型 ,指定了通过访问共享数据块事件 、通过基于共享内存缓冲区的TypedArray
实例以及通过 Atomics 对象的方法而产生的事件的可能排序。当程序没有数据竞争(下文定义)时,事件的排序表现为顺序一致,即作为每个代理 的操作的交错。当程序存在数据竞争时,共享内存操作可能表现为顺序不一致。例如,程序可能表现出违反因果关系的行为和其他令人惊讶的现象。这些惊讶现象源于编译器变换和
CPU 的设计(例如,乱序执行和推测)。内存模型定义了程序表现为顺序一致行为的精确条件,以及从数据竞争中读取的可能值。也就是说,没有未定义行为。
内存模型定义为在评估期间由抽象操作 对
SharedArrayBuffer 或由 Atomics 对象的方法引入的事件的关系约束。
注
本节提供了有关SharedArrayBuffers
上的抽象操作 引入的事件的公理化模型。需要强调的是,该模型不像本规范的其余部分那样可以算法化表达。抽象操作
对事件的非确定性引入是 ECMAScript
评估的操作语义与内存模型的公理语义之间的接口。这些事件的语义通过考虑评估中的所有事件的图来定义。这些既不是静态语义,也不是运行时语义。没有演示的算法实现,而是一组约束,决定特定事件图是否被允许或禁止。
29.1 内存模型基础
共享内存访问(读和写)被分为两组:原子访问和数据访问,定义如下。原子访问是顺序一致的,即所有代理 在代理集群 中达成了事件的严格总排序。非原子访问没有所有代理 达成的严格总排序,即无序的。
注 1
不支持比顺序一致性更弱而比无序更强的排序,例如释放-获取。
共享数据块事件 是ReadSharedMemory 、WriteSharedMemory 或ReadModifyWriteSharedMemory 记录 。
表 91: ReadSharedMemory
事件字段
字段名称
值
含义
[[Order]]
seq-cst 或 unordered
事件的最弱排序由内存模型 保证。
[[NoTear]]
布尔值
该事件是否允许从多个具有相等范围的写事件中读取。
[[Block]]
一个共享数据块
事件操作的块。
[[ByteIndex]]
一个非负的整数
在[[Block]] 中的读取字节地址。
[[ElementSize]]
一个非负的整数
读取的大小。
表 92: WriteSharedMemory
事件字段
字段名称
值
含义
[[Order]]
seq-cst 、unordered 或 init
事件的最弱排序由内存模型 保证。
[[NoTear]]
布尔值
该事件是否允许被多个具有相等范围的读取事件读取。
[[Block]]
一个共享数据块
事件操作的块。
[[ByteIndex]]
一个非负的整数
在[[Block]] 中的写入字节地址。
[[ElementSize]]
一个非负的整数
写入的大小。
[[Payload]]
一个列表
的字节值
其他事件将读取的列表
的字节值 。
表 93: ReadModifyWriteSharedMemory
事件字段
字段名称
值
含义
[[Order]]
seq-cst
读-修改-写事件始终是顺序一致的。
[[NoTear]]
true
读-修改-写事件不能发生撕裂。
[[Block]]
一个共享数据块
事件操作的块。
[[ByteIndex]]
一个非负的整数
在[[Block]] 中的读-修改-写字节地址。
[[ElementSize]]
一个非负的整数
读-修改-写的大小。
[[Payload]]
一个列表
的字节值
将传递给[[ModifyOp]] 的列表
的字节值 。
[[ModifyOp]]
一个读-修改-写修改函数
一个抽象的闭包,返回一个修改后的列表
的字节值 ,从读取的列表
的字节值 和[[Payload]] 中得到。
这些事件是通过抽象操作
或通过 Atomics 对象上的方法引入的。
某些操作可能还会引入同步 事件。同步事件 没有字段,仅存在于直接约束其他事件的允许排序。
除了共享数据块 和同步事件之外,还有宿主 特定的事件。
假设 ReadSharedMemory、WriteSharedMemory 或 ReadModifyWriteSharedMemory 事件的范围是从其[[ByteIndex]] 到[[ByteIndex]] + [[ElementSize]] - 1 的连续整数 的集合。当事件具有相同的[[Block]] 且范围逐元素相等时,两事件的范围是相等的。当事件具有相同的[[Block]] 、范围不相等且它们的交集非空时,两事件的范围是重叠的。当事件没有相同的[[Block]] 或它们的范围既不相等也不重叠时,两事件的范围是分离的。
注 2
应考虑的宿主 特定同步事件示例包括:将 SharedArrayBuffer 从一个代理
发送到另一个(例如,通过浏览器中的postMessage
),启动和停止代理 ,以及通过除共享内存以外的通道
在代理集群 内通信。假设这些事件在评估时像其他
SharedArrayBuffer 事件一样附加到代理顺序 。
事件在候选执行 中按照下面定义的关系排序。
29.2 代理事件记录
代理事件记录 是一个记录 ,具有以下字段。
表 94: 代理事件记录 字段
字段名称
值
含义
[[AgentSignifier]]
一个代理标识符
产生此排序的代理 。
[[EventList]]
一个事件列表
事件在评估期间附加到列表中。
[[AgentSynchronizesWith]]
一个对列表
的同步事件
同步 关系由操作语义引入。
29.3 选择值记录
选择值记录 是一个记录 ,具有以下字段。
表 95: 选择值记录 字段
29.4 候选执行
候选执行 是代理集群 的评估的一个记录 ,具有以下字段。
表 96: 候选执行记录 字段
空候选执行 是一个候选执行记录 ,其字段是空的列表 和关系 。
29.5 内存模型的抽象操作
29.5.1 EventSet ( execution )
抽象操作 EventSet 接受一个参数 execution (一个候选执行 ),并返回一个事件集合。调用时执行以下步骤:
1. 将 events 设为空集合。
2. 对于 execution .[[EventsRecords]]
中的每个代理事件记录 aer ,执行
a. 对于 aer .[[EventList]] 中的每个事件
E ,执行
i. 将 E 添加到 events 中。
3. 返回 events 。
29.5.2 SharedDataBlockEventSet ( execution )
抽象操作 SharedDataBlockEventSet 接受一个参数 execution (一个候选执行 ),并返回一个事件集合。调用时执行以下步骤:
1. 将 events 设为空集合。
2. 对于EventSet (execution ) 中的每个事件
E ,执行
a. 如果 E 是 ReadSharedMemory 、
WriteSharedMemory ,
或 ReadModifyWriteSharedMemory
事件,将 E 添加到 events 中。
3. 返回 events 。
29.5.3 HostEventSet ( execution )
抽象操作 HostEventSet 接受一个参数 execution (一个候选执行 ),并返回一个事件集合。调用时执行以下步骤:
1. 将 events 设为空集合。
2. 对于EventSet (execution ) 中的每个事件
E ,执行
a. 如果 E 不在 SharedDataBlockEventSet (execution )
中,
将 E 添加到 events 中。
3. 返回 events 。
29.5.4 ComposeWriteEventBytes ( execution , byteIndex ,
Ws )
抽象操作 ComposeWriteEventBytes 接受三个参数:execution (一个候选执行 )、byteIndex (一个非负整数 )和
Ws (一个列表 ,包含WriteSharedMemory 或
ReadModifyWriteSharedMemory
事件),并返回一个列表 ,其中包含字节值 。调用时执行以下步骤:
1. 将 byteLocation 设为 byteIndex 。
2. 将 bytesRead 设为一个新的空列表 。
3. 对于 Ws 中的每个元素 W ,执行
a. 断言 :W 在其范围内包含
byteLocation 。
b. 将 payloadIndex 设为 byteLocation -
W .[[ByteIndex]] 。
c. 如果 W 是一个WriteSharedMemory
事件,则
i. 将 byte 设为 W .[[Payload]] [payloadIndex ]。
d. 否则,
i. 断言 :W 是一个ReadModifyWriteSharedMemory
事件。
ii. 将 bytes 设为ValueOfReadEvent (execution ,
W )。
iii. 将 bytesModified 设为 W .[[ModifyOp]] (bytes , W .[[Payload]] )。
iv. 将 byte 设为
bytesModified [payloadIndex ]。
e. 将 byte 添加到 bytesRead 。
f. 将 byteLocation 设为 byteLocation + 1。
4. 返回 bytesRead 。
注 1
读-修改-写修改操作 [[ModifyOp]] 由 Atomics 对象上的函数属性提供,这些属性引入了ReadModifyWriteSharedMemory
事件。
注 2
29.5.5 ValueOfReadEvent ( execution , R )
抽象操作 ValueOfReadEvent 接受两个参数:execution (一个候选执行 )和
R (一个ReadSharedMemory 或
ReadModifyWriteSharedMemory
事件),并返回一个列表 ,其中包含字节值 。调用时执行以下步骤:
1. 将 Ws 设为 execution .[[ReadsBytesFrom]] (R )。
2. 断言 :Ws 是一个列表 ,包含WriteSharedMemory 或ReadModifyWriteSharedMemory
事件,且长度等于 R .[[ElementSize]] 。
3. 返回ComposeWriteEventBytes (execution ,
R .[[ByteIndex]] , Ws )。
29.6 候选执行的关系
29.6.1 代理顺序
对于一个 候选执行
execution ,execution .[[AgentOrder]] 是一个 关系
在事件上的关系,满足以下条件。
对于每一对 (E , D ) 在 事件集 (execution ),
execution .[[AgentOrder]] 包含 (E , D ),如果
存在某个 代理事件记录
aer 在 execution .[[EventsRecords]] 中,使得
E
和 D 都在 aer .[[EventList]] 中,并且 E 在
D 之前,按照 列表 顺序
排列。
注
每个 代理
在评估过程中引入事件的每个代理
产生一个 代理
严格总序 。
这是这些 严格总序 的
并集。
29.6.2 读取字节来源
对于一个 候选执行
execution ,execution .[[ReadsBytesFrom]] 是一个数学
函数,将 共享数据块事件集 (execution )
中的事件映射到 列表 中的事件,
这些事件也在 共享数据块事件集 (execution )
中,满足以下条件:
29.6.3 reads-from
对于一个 候选执行
execution ,execution .[[ReadsFrom]] 是一个最小的 关系 ,
该关系满足以下条件:
对于每一对 (R , W ) 在 共享数据块事件集 (execution ),
如果 execution .[[ReadsBytesFrom]] (R ) 包含 W ,
则 execution .[[ReadsFrom]] 包含 (R , W )。
29.6.4 host-synchronizes-with
对于一个 候选执行
execution ,execution .[[HostSynchronizesWith]] 是一个
宿主 提供的
严格部分顺序 ,
作用于 宿主
特定的事件,满足以下至少条件:
如果 execution .[[HostSynchronizesWith]] 包含 (E ,
D ),则 E 和 D 必须在 宿主事件集 (execution ) 中。
在 execution .[[HostSynchronizesWith]] 和 execution .[[AgentOrder]] 的并集中没有循环。
注 1
对于两个 宿主
特定的事件 E 和
D ,E 宿主同步 D 意味着 E 先发生于
D 。
注 2
宿主同步关系允许宿主提供额外的同步机制,例如 HTML 工作者之间的 postMessage
。
29.6.5 synchronizes-with
对于一个 候选执行
execution ,execution .[[SynchronizesWith]] 是一个最小的
关系 ,
该关系满足以下条件:
对于每一对 (R , W ) 在 execution .[[ReadsFrom]] 中,
如果 R .[[Order]] 是 seq-cst ,
W .[[Order]] 是 seq-cst ,并且 R
和 W 具有相等的范围,则 execution .[[SynchronizesWith]]
包含 (W , R )。
对于 execution .[[EventsRecords]] 的每个元素 eventsRecord ,
以下条件成立:
对于 eventsRecord .[[AgentSynchronizesWith]] 中的每一对 (S ,
Sw ),
execution .[[SynchronizesWith]] 包含 (S , Sw )。
对于 execution .[[HostSynchronizesWith]] 中的每一对 (E ,
D ),
execution .[[SynchronizesWith]] 包含 (E , D )。
注 1
由于惯例,写事件与读事件之间是同步的,而不是读事件与写事件之间同步。
注 2
init 事件不参与同步,而是直接受到 先发生于 的约束。
注 3
并非所有由 reads-from 关系关联的
seq-cst 事件
都由 synchronizes-with 关系关联。只有那些也具有相等范围的事件才由 synchronizes-with 关系关联。
注 4
对于 共享数据块事件 R 和
W ,
如果 W 与 R 之间存在同步关系,则 R 可能 reads-from 其他的写操作,而不仅仅是 W 。
29.6.6 happens-before
对于一个 候选执行
execution ,execution .[[HappensBefore]] 是一个最小的
关系 ,
该关系满足以下条件:
对于 execution .[[AgentOrder]] 中的每一对 (E , D ),
execution .[[HappensBefore]] 包含 (E , D )。
对于 execution .[[SynchronizesWith]] 中的每一对 (E ,
D ),
execution .[[HappensBefore]] 包含 (E , D )。
对于 共享数据块事件集 (execution )
中的每一对 (E , D ),
execution .[[HappensBefore]] 包含 (E , D )
如果 E .[[Order]] 是 init ,并且 E 和
D 具有重叠的范围。
对于 事件集 (execution ) 中的每一对
(E , D ),
execution .[[HappensBefore]] 包含 (E , D )
如果存在一个事件 F ,使得对 (E , F ) 和 (F , D ) 都在
execution .[[HappensBefore]] 中。
注
由于 happens-before 是 agent-order 的超集,候选执行
与 ECMAScript 的单线程求值语义是一致的。
29.7 有效执行的属性
29.7.1 有效选择读取
一个 候选执行
执行 只有在以下算法返回 true 时,才具有有效的选择读取。
1. 对于每一个 ReadSharedMemory
或 ReadModifyWriteSharedMemory
事件 R 属于 SharedDataBlockEventSet (执行 ),
执行以下步骤
a. 设 chosenValueRecord 为
执行 .[[ChosenValues]] 中 [[Event]] 字段为
R 的元素。
b. 设 chosenValue 为
chosenValueRecord .[[ChosenValue]] 。
c. 设 readValue 为 ValueOfReadEvent (执行 ,
R ).
d. 设 chosenLen 为
chosenValue 中元素的数量。
e. 设 readLen 为
readValue 中元素的数量。
f. 如果 chosenLen ≠ readLen ,则
i. 返回 false 。
g. 如果对于某个 整数 i 在从 0(含)到
chosenLen (不含)的 区间
中,chosenValue [i ] ≠
readValue [i ],则
i. 返回 false 。
2. 返回 true 。
29.7.2 一致读取
一个 候选执行
执行 只有在以下算法返回 true 时,才具有一致读取。
1. 对于每一个 ReadSharedMemory
或 ReadModifyWriteSharedMemory
事件 R 属于 SharedDataBlockEventSet (执行 ),
执行以下步骤
a. 设 Ws 为 执行 .[[ReadsBytesFrom]] (R ).
b. 设 byteLocation 为 R .[[ByteIndex]] .
c. 对于 Ws 中的每一个元素 W ,执行以下步骤
i. 如果 执行 .[[HappensBefore]]
包含 (R , W ),则
1. 返回 false 。
ii. 如果存在一个 WriteSharedMemory
或 ReadModifyWriteSharedMemory
事件 V 其范围包含 byteLocation ,且使得 (W , V ) 和
(V , R ) 的对在 执行 .[[HappensBefore]]
中存在,则
1. 返回 false 。
iii. 将 byteLocation 设为
byteLocation + 1。
2. 返回 true 。
29.7.3 无撕裂读取
一个 候选执行
执行 只有在以下算法返回 true 时,才具有无撕裂读取。
1. 对于每一个 ReadSharedMemory
或 ReadModifyWriteSharedMemory
事件 R 属于 SharedDataBlockEventSet (执行 ),
执行以下步骤
a. 如果 R .[[NoTear]] 是
true ,则
i. Assert : 设 R .[[ByteIndex]] 除以 R .[[ElementSize]]
的余数为 0。
ii. 对于每一个事件 W ,使得
执行 .[[ReadsFrom]] 包含 (R ,
W ) 且 W .[[NoTear]] 是
true ,执行以下步骤
1. 如果 R 和 W 的范围相等,并且
存在事件 V 使得 V 和 W 的范围相等且 V .[[NoTear]] 为
true ,且 W 不是 V ,并且 执行 .[[ReadsFrom]] 包含 (R , V ), 则
a. 返回 false 。
2. 返回 true 。
注
事件的 [[NoTear]] 字段在事件通过访问 整数 TypedArray 引入时为
true ,
而通过访问浮点 TypedArray 或
DataView 引入时为 false 。
直观地说,这个要求是,当通过对齐的方式访问内存范围时,必须保证该范围上的单个写事件在与其他具有相同范围的写事件的竞争中“获胜”。更准确地说,这个要求表示对齐的读取事件不能读取由多个具有相同范围的写事件组合而成的值。然而,对齐的读取事件可以从多个具有重叠范围的写事件中读取。
29.7.4 顺序一致的原子操作
对于一个 候选执行
执行 ,内存顺序是 严格
总顺序 的所有事件在 事件集 (执行 ) 中,满足以下条件。
一个 候选执行 具有
顺序一致的原子操作,如果存在一个内存顺序。
注 3
虽然内存顺序包括了 事件集 (执行 ) 中的所有事件,
但那些不受 happens-before 或 synchronizes-with 约束的事件,
可以在顺序中的任何位置发生。
29.7.5 有效执行
一个 候选执行
执行 是一个有效的执行(或简称为执行),如果以下所有条件都成立。
宿主
提供了一个 宿主同步
关系
用于 执行 .[[HostSynchronizesWith]] 。
执行 .[[HappensBefore]] 是一个 严格的偏序 。
执行 具有有效的选定读取。
执行 具有一致的读取。
执行 具有无撕裂读取。
执行 具有顺序一致的原子操作。
所有程序至少有一个有效的执行。
29.8 竞态
对于一个执行 执行 ,如果以下算法返回 true ,则 E 和 D 在 共享数据块事件集 (执行 )
中是竞态的。
1. 如果 E 不等于 D ,则
a. 如果对 (E , D ) 和 (D , E )
的配对不在 执行 .[[HappensBefore]] 中,则
i. 如果 E 和 D 都是 写共享内存
或 读修改写共享内存
事件,并且 E 和 D 的范围不互斥,则
1. 返回 true 。
ii. 如果 执行 .[[ReadsFrom]] 包含
(E , D ) 或 (D , E ),则
1. 返回 true 。
2. 返回 false 。
29.9 数据竞态
对于一个执行 执行 ,如果以下算法返回 true ,则 E 和 D 在 共享数据块事件集 (执行 )
中是数据竞态的。
1. 如果 E 和 D 在 执行 中是竞态,则
a. 如果 E .[[Order]] 不是
seq-cst 或 D .[[Order]] 不是
seq-cst ,则
i. 返回 true 。
b. 如果 E 和 D 的范围重叠,则
i. 返回 true 。
2. 返回 false 。
29.10 数据竞态自由
如果在 共享数据块事件集 (执行 )
中没有两个事件发生数据竞态,则执行 执行 是数据竞态自由的。
如果一个程序的所有执行都是数据竞态自由的,则该程序是数据竞态自由的。
内存模型 保证数据竞态自由程序中所有事件的顺序一致性。
29.11 共享内存指南
注 1
以下是 ECMAScript 程序员在使用共享内存时的指南。
我们建议程序保持数据竞态自由,即确保同一内存位置上不可能同时进行非原子操作。数据竞态自由的程序具有交错语义,其中每个 代理 的评估语义中的每一步都与其他步骤交错。对于数据竞态自由的程序,不需要理解
内存模型 的细节。这些细节不太可能帮助更好地编写 ECMAScript。
更一般地,即使程序不是数据竞态自由的,只要原子操作不涉及任何数据竞态,并且所有竞态操作具有相同的访问大小,程序也可能具有可预测的行为。安排原子操作不参与竞态的最简单方法是确保原子操作和非原子操作使用不同的内存单元,并且不同大小的原子访问不会同时访问相同的单元。实际上,程序应该尽可能将共享内存视为强类型的。虽然不能依赖于竞态的非原子访问的排序和时序,但如果内存被视为强类型,竞态访问将不会“撕裂”(其值的位不会混合)。
注 2
以下是 ECMAScript 实现者为使用共享内存的程序生成编译器转换的指南。
在多 代理
环境中,允许大多数在单 代理 环境中有效的程序转换,以确保每个 代理 在多 代理 程序中的性能与在单 代理
环境中相同。通常,这些转换很难判断。我们概述了一些关于程序转换的规则,这些规则被认为是规范性的(即它们由 内存模型 或者比 内存模型 所暗示的更强),但可能并不全面。这些规则适用于引入构成
代理顺序 的事件之前的程序转换。
让 代理顺序切片 是与单个 代理 相关的 代理顺序 的子集。
让 可能的读取值 是在所有有效执行中,对该事件的 读取事件的值 的所有值的集合。
在共享内存存在的情况下,任何在没有共享内存的情况下有效的代理顺序切片转换都是有效的,以下除外。
原子操作不可更改 :程序转换不得使代理顺序切片中的 seq-cst 事件与其
unordered 操作重新排序,也不得使其 seq-cst 操作与彼此重新排序,程序转换也不得从
代理顺序 中删除
seq-cst 操作。
(实际上,禁止重新排序强制编译器假定每个 seq-cst 操作是同步的,并包含在最终的 内存顺序
中,这通常在没有跨代理程序分析的情况下必须假定。它还强制编译器假定每个对 内存顺序 的调用可能包含
seq-cst 操作。)
读取必须稳定 :任何给定的共享内存读取必须在一个执行中只观察到一个值。
(例如,如果程序中的语义上单个读取被多次执行,则程序随后只能观察到读取的一个值。被称为重新物化的转换可能违反此规则。)
写入必须稳定 :所有可观察的写入必须符合执行中的程序语义。
(例如,转换不得引入某些可观察的写入,如通过对更大位置进行读-修改-写操作以写入较小的数据项、将值写入程序无法写入的内存,或将刚读取的值写回其读取的原位置,如果该位置可能被另一个 代理 在读取之后覆盖。)
可能的读取值必须非空 :程序转换不能使共享内存读取的可能读取值变为空。
(反直觉地,这条规则实际上限制了对写入的转换,因为写入在 内存模型 中具有强制性,以便被读取事件读取。例如,写入可以在两个
seq-cst 操作之间移动、合并和有时重新排序,但转换不能删除更新位置的所有写入;一些写入必须保留。)
仍然有效的转换示例包括:合并来自同一位置的多个非原子读取、重新排序非原子读取、引入猜测的非原子读取、合并对同一位置的多个非原子写入、重新排序对不同位置的非原子写入,以及即使这影响终止也将非原子读取提升出循环。一般来说,需要注意
的是,别名的 TypedArrays 使得证明位置不同变得困难。
注 3
以下是 ECMAScript 实现者为共享内存访问生成机器代码的指南。
对于内存模型不弱于 ARM 或 Power
的体系结构,非原子存储和加载可以编译为目标体系结构上的裸存储和加载。原子存储和加载可以编译为保证顺序一致性的指令。如果不存在这样的指令,则应使用内存屏障,例如在裸存储或加载的两侧放置屏障。读-修改-写操作可以编译为目标体系结构上的读-修改-写指令,例如
x86 上的 LOCK
前缀指令、ARM 上的加载排他/存储排他指令以及 Power 上的加载链接/存储条件指令。
具体来说,内存模型 旨在允许以下代码生成。
程序中的每个原子操作都被假定为必要的。
原子操作从未与其他原子操作或非原子操作重新排列。
函数总是被假定执行原子操作。
原子操作从未实现为对较大数据的读-修改-写操作,而是作为非锁自由原子操作,如果平台没有适当大小的原子操作。(我们已经假定每个平台都有每种感兴趣大小的正常内存访问操作。)
简单的代码生成使用以下模式:
常规加载和存储编译为单个加载和存储指令。
无锁原子加载和存储编译为一个完整(顺序一致)的屏障、一个常规加载或存储,以及一个完整的屏障。
无锁原子读-修改-写访问编译为一个完整的屏障、一个原子读-修改-写指令序列,以及一个完整的屏障。
非无锁原子操作编译为一个自旋锁获取、一个完整的屏障、一系列非原子加载和存储指令、一个完整的屏障以及一个自旋锁释放。
只要地址范围上的原子操作不会与非原子写入或不同大小的原子操作发生竞态,那么这种映射就是正确的。然而,这就是我们需要的:内存模型
实质上将涉及竞态的原子操作降级为非原子状态。另一方面,简单的映射相当强大:它允许将原子操作用作顺序一致性屏障,而 内存模型 实际上并未保证这一点。
对这些基本模式的本地改进也是允许的,但须遵循 内存模型 的约束。例如:
显而易见的依赖平台的改进可以去除多余的屏障。例如,在 x86 上,无锁原子加载和存储周围的屏障通常可以省略,除非是在存储之后的屏障,且对于无锁读-修改-写指令不需要任何屏障,因为这些都使用
LOCK
前缀指令。在许多平台上有多种强度的屏障,可以在某些上下文中使用较弱的屏障而不会破坏顺序一致性。
大多数现代平台支持所有 ECMAScript 原子操作所需的数据大小的无锁原子操作。如果需要非无锁原子操作,通常可以将围绕原子操作主体的屏障折叠到锁和解锁步骤中。非无锁原子操作的最简单解决方案是在每个
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
$
<ZWNJ>
<ZWJ>
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 MV of HexDigits > 0x10FFFF
CodePoint ::
HexDigits [~Sep]
but only if 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]
)
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 Functions and Classes
UniqueFormalParameters [Yield,
Await] :
FormalParameters [?Yield,
?Await]
FormalParameters [Yield,
Await] :
[empty]
FunctionRestParameter [?Yield,
?Await]
FormalParameterList [?Yield,
?Await]
FormalParameterList [?Yield,
?Await]
,
FormalParameterList [?Yield,
?Await]
,
FunctionRestParameter [?Yield,
?Await]
FormalParameterList [Yield,
Await] :
FormalParameter [?Yield,
?Await]
FormalParameterList [?Yield,
?Await]
,
FormalParameter [?Yield,
?Await]
FunctionRestParameter [Yield,
Await] :
BindingRestElement [?Yield,
?Await]
FormalParameter [Yield,
Await] :
BindingElement [?Yield,
?Await]
FunctionDeclaration [Yield,
Await, Default] :
function
BindingIdentifier [?Yield,
?Await]
(
FormalParameters [~Yield,
~Await]
)
{
FunctionBody [~Yield,
~Await]
}
[+Default]
function
(
FormalParameters [~Yield,
~Await]
)
{
FunctionBody [~Yield,
~Await]
}
FunctionExpression
:
function
BindingIdentifier [~Yield,
~Await] opt
(
FormalParameters [~Yield,
~Await]
)
{
FunctionBody [~Yield,
~Await]
}
FunctionBody [Yield,
Await] :
FunctionStatementList [?Yield,
?Await]
FunctionStatementList [Yield,
Await] :
StatementList [?Yield,
?Await, +Return] opt
ArrowFunction [In, Yield,
Await] :
ArrowParameters [?Yield,
?Await]
[no LineTerminator
here]
=>
ConciseBody [?In]
ArrowParameters [Yield,
Await] :
BindingIdentifier [?Yield,
?Await]
CoverParenthesizedExpressionAndArrowParameterList [?Yield,
?Await]
ConciseBody [In]
:
[lookahead ≠ { ]
ExpressionBody [?In,
~Await]
{
FunctionBody [~Yield,
~Await]
}
ExpressionBody [In,
Await] :
AssignmentExpression [?In,
~Yield, ?Await]
在处理生产规则的实例时
ArrowParameters [Yield,
Await] :
CoverParenthesizedExpressionAndArrowParameterList [?Yield,
?Await]
CoverParenthesizedExpressionAndArrowParameterList
的解释使用以下语法进行细化:
ArrowFormalParameters [Yield,
Await] :
(
UniqueFormalParameters [?Yield,
?Await]
)
AsyncArrowFunction [In,
Yield, Await] :
async
[no LineTerminator
here]
AsyncArrowBindingIdentifier [?Yield]
[no LineTerminator
here]
=>
AsyncConciseBody [?In]
CoverCallExpressionAndAsyncArrowHead [?Yield,
?Await]
[no LineTerminator
here]
=>
AsyncConciseBody [?In]
AsyncConciseBody [In]
:
[lookahead ≠ { ]
ExpressionBody [?In,
+Await]
{
AsyncFunctionBody
}
AsyncArrowBindingIdentifier [Yield]
:
BindingIdentifier [?Yield,
+Await]
CoverCallExpressionAndAsyncArrowHead [Yield,
Await] :
MemberExpression [?Yield,
?Await]
Arguments [?Yield,
?Await]
在处理生产规则的实例时
AsyncArrowFunction [In,
Yield, Await] :
CoverCallExpressionAndAsyncArrowHead [?Yield,
?Await]
[no LineTerminator
here]
=>
AsyncConciseBody [?In]
CoverCallExpressionAndAsyncArrowHead
的解释使用以下语法进行细化:
AsyncArrowHead
:
async
[no LineTerminator
here]
ArrowFormalParameters [~Yield,
+Await]
MethodDefinition [Yield,
Await] :
ClassElementName [?Yield,
?Await]
(
UniqueFormalParameters [~Yield,
~Await]
)
{
FunctionBody [~Yield,
~Await]
}
GeneratorMethod [?Yield,
?Await]
AsyncMethod [?Yield,
?Await]
AsyncGeneratorMethod [?Yield,
?Await]
get
ClassElementName [?Yield,
?Await]
(
)
{
FunctionBody [~Yield,
~Await]
}
set
ClassElementName [?Yield,
?Await]
(
PropertySetParameterList
)
{
FunctionBody [~Yield,
~Await]
}
PropertySetParameterList
:
FormalParameter [~Yield,
~Await]
GeneratorDeclaration [Yield,
Await, Default] :
function
*
BindingIdentifier [?Yield,
?Await]
(
FormalParameters [+Yield,
~Await]
)
{
GeneratorBody
}
[+Default]
function
*
(
FormalParameters [+Yield,
~Await]
)
{
GeneratorBody
}
GeneratorExpression
:
function
*
BindingIdentifier [+Yield,
~Await] opt
(
FormalParameters [+Yield,
~Await]
)
{
GeneratorBody
}
GeneratorMethod [Yield,
Await] :
*
ClassElementName [?Yield,
?Await]
(
UniqueFormalParameters [+Yield,
~Await]
)
{
GeneratorBody
}
GeneratorBody
:
FunctionBody [+Yield,
~Await]
YieldExpression [In,
Await] :
yield
yield
[no LineTerminator
here]
AssignmentExpression [?In,
+Yield, ?Await]
yield
[no LineTerminator
here]
*
AssignmentExpression [?In,
+Yield, ?Await]
AsyncGeneratorDeclaration [Yield,
Await, Default] :
async
[no LineTerminator
here]
function
*
BindingIdentifier [?Yield,
?Await]
(
FormalParameters [+Yield,
+Await]
)
{
AsyncGeneratorBody
}
[+Default]
async
[no LineTerminator
here]
function
*
(
FormalParameters [+Yield,
+Await]
)
{
AsyncGeneratorBody
}
AsyncGeneratorExpression
:
async
[no LineTerminator
here]
function
*
BindingIdentifier [+Yield,
+Await] opt
(
FormalParameters [+Yield,
+Await]
)
{
AsyncGeneratorBody
}
AsyncGeneratorMethod [Yield,
Await] :
async
[no LineTerminator
here]
*
ClassElementName [?Yield,
?Await]
(
UniqueFormalParameters [+Yield,
+Await]
)
{
AsyncGeneratorBody
}
AsyncGeneratorBody
:
FunctionBody [+Yield,
+Await]
AsyncFunctionDeclaration [Yield,
Await, Default] :
async
[no LineTerminator
here]
function
BindingIdentifier [?Yield,
?Await]
(
FormalParameters [~Yield,
+Await]
)
{
AsyncFunctionBody
}
[+Default]
async
[no LineTerminator
here]
function
(
FormalParameters [~Yield,
+Await]
)
{
AsyncFunctionBody
}
AsyncFunctionExpression
:
async
[no LineTerminator
here]
function
BindingIdentifier [~Yield,
+Await] opt
(
FormalParameters [~Yield,
+Await]
)
{
AsyncFunctionBody
}
AsyncMethod [Yield,
Await] :
async
[no LineTerminator
here]
ClassElementName [?Yield,
?Await]
(
UniqueFormalParameters [~Yield,
+Await]
)
{
AsyncFunctionBody
}
AsyncFunctionBody
:
FunctionBody [~Yield,
+Await]
AwaitExpression [Yield]
:
await
UnaryExpression [?Yield,
+Await]
ClassDeclaration [Yield,
Await, Default] :
class
BindingIdentifier [?Yield,
?Await]
ClassTail [?Yield,
?Await]
[+Default]
class
ClassTail [?Yield,
?Await]
ClassExpression [Yield,
Await] :
class
BindingIdentifier [?Yield,
?Await] opt
ClassTail [?Yield,
?Await]
ClassTail [Yield,
Await] :
ClassHeritage [?Yield,
?Await] opt
{
ClassBody [?Yield,
?Await] opt
}
ClassHeritage [Yield,
Await] :
extends
LeftHandSideExpression [?Yield,
?Await]
ClassBody [Yield,
Await] :
ClassElementList [?Yield,
?Await]
ClassElementList [Yield,
Await] :
ClassElement [?Yield,
?Await]
ClassElementList [?Yield,
?Await]
ClassElement [?Yield,
?Await]
ClassElement [Yield,
Await] :
MethodDefinition [?Yield,
?Await]
static
MethodDefinition [?Yield,
?Await]
FieldDefinition [?Yield,
?Await]
;
static
FieldDefinition [?Yield,
?Await]
;
ClassStaticBlock
;
FieldDefinition [Yield,
Await] :
ClassElementName [?Yield,
?Await]
Initializer [+In, ?Yield,
?Await] opt
ClassElementName [Yield,
Await] :
PropertyName [?Yield,
?Await]
PrivateIdentifier
ClassStaticBlock
:
static
{
ClassStaticBlockBody
}
ClassStaticBlockBody
:
ClassStaticBlockStatementList
ClassStaticBlockStatementList
:
StatementList [~Yield,
+Await, ~Return] opt
A.5 脚本和模块
Script :
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
;
import
ModuleSpecifier
;
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]
ExportDeclaration
:
export
ExportFromClause
FromClause
;
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 :::
TemporalSign
Hour
TemporalSign
Hour
HourSubcomponents [+Extended]
TemporalSign
Hour
HourSubcomponents [~Extended]
TemporalSign
:::
ASCIISign
<MINUS>
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]
)
(?:
Disjunction [?UnicodeMode,
?UnicodeSetsMode, ?NamedCaptureGroups]
)
SyntaxCharacter
:: one of ^ $
\ . * + ? (
) [ ] { }
|
PatternCharacter
::
SourceCharacter
but not SyntaxCharacter
AtomEscape [UnicodeMode,
NamedCaptureGroups] ::
DecimalEscape
CharacterClassEscape [?UnicodeMode]
CharacterEscape [?UnicodeMode]
[+NamedCaptureGroups]
k
GroupName [?UnicodeMode]
CharacterEscape [UnicodeMode]
::
ControlEscape
c
AsciiLetter
0
[lookahead ∉ DecimalDigit ]
HexEscapeSequence
RegExpUnicodeEscapeSequence [?UnicodeMode]
IdentityEscape [?UnicodeMode]
ControlEscape
:: one of f n
r t v
GroupSpecifier [UnicodeMode]
::
?
GroupName [?UnicodeMode]
GroupName [UnicodeMode]
::
<
RegExpIdentifierName [?UnicodeMode]
>
RegExpIdentifierName [UnicodeMode]
::
RegExpIdentifierStart [?UnicodeMode]
RegExpIdentifierName [?UnicodeMode]
RegExpIdentifierPart [?UnicodeMode]
RegExpIdentifierStart [UnicodeMode]
::
IdentifierStartChar
\
RegExpUnicodeEscapeSequence [+UnicodeMode]
[~UnicodeMode]
UnicodeLeadSurrogate
UnicodeTrailSurrogate
RegExpIdentifierPart [UnicodeMode]
::
IdentifierPartChar
\
RegExpUnicodeEscapeSequence [+UnicodeMode]
[~UnicodeMode]
UnicodeLeadSurrogate
UnicodeTrailSurrogate
RegExpUnicodeEscapeSequence [UnicodeMode]
:: [+UnicodeMode]
u
HexLeadSurrogate
\u
HexTrailSurrogate
[+UnicodeMode]
u
HexLeadSurrogate
[+UnicodeMode]
u
HexTrailSurrogate
[+UnicodeMode]
u
HexNonSurrogate
[~UnicodeMode]
u
Hex4Digits
[+UnicodeMode]
u{
CodePoint
}
UnicodeLeadSurrogate
::
any Unicode code point in the inclusive interval from U+D800 to U+DBFF
UnicodeTrailSurrogate
::
any Unicode code point in the inclusive interval from U+DC00 to U+DFFF
每个 \u
HexTrailSurrogate 的选择,其中关联的
u
HexLeadSurrogate 是模棱两可的,应与最近的可能的
u
HexLeadSurrogate 关联,该 u
原本没有对应的 \u
HexTrailSurrogate 。
HexLeadSurrogate
::
Hex4Digits
but only if the MV of Hex4Digits is in the inclusive
interval from 0xD800 to 0xDBFF
HexTrailSurrogate
::
Hex4Digits
but only if the MV of Hex4Digits is in the inclusive
interval from 0xDC00 to 0xDFFF
HexNonSurrogate
::
Hex4Digits
but only if the MV of Hex4Digits is not in the inclusive
interval from 0xD800 to 0xDFFF
IdentityEscape [UnicodeMode]
:: [+UnicodeMode]
SyntaxCharacter
[+UnicodeMode]
/
[~UnicodeMode]
SourceCharacter
but not UnicodeIDContinue
DecimalEscape
::
NonZeroDigit
DecimalDigits [~Sep] opt
[lookahead ∉ DecimalDigit ]
CharacterClassEscape [UnicodeMode]
::
d
D
s
S
w
W
[+UnicodeMode]
p{
UnicodePropertyValueExpression
}
[+UnicodeMode]
P{
UnicodePropertyValueExpression
}
UnicodePropertyValueExpression
::
UnicodePropertyName
=
UnicodePropertyValue
LoneUnicodePropertyNameOrValue
UnicodePropertyName
::
UnicodePropertyNameCharacters
UnicodePropertyNameCharacters
::
UnicodePropertyNameCharacter
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 额外的 ECMAScript 功能用于 Web 浏览器
当 ECMAScript 宿主
是 Web 浏览器时,本附录中定义的 ECMAScript 语言语法和语义是必需的。如果 ECMAScript 宿主 不是 Web 浏览器,则本附录的内容是规范性的但可选的。
注
本附录描述了 Web 浏览器 ECMAScript 宿主
的各种遗留特性和其他特征。所有在本附录中指定的语言特性和行为都有一个或多个不希望出现的特征,如果没有遗留使用,这些特性将被从本规范中删除。然而,由于大量现有网页使用这些特性,Web
浏览器必须继续支持它们。本附录中的规范定义了这些遗留特性可互操作实现的要求。
这些特性不被视为 ECMAScript 语言的核心部分。程序员在编写新的 ECMAScript 代码时不应使用或假设这些特性和行为的存在。除非实现是 Web 浏览器的一部分或需要运行 Web 浏览器遇到的相同遗留
ECMAScript 代码,否则不鼓励 ECMAScript 实现包含这些特性。
B.1 Additional Syntax
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]
)
(?:
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.5
的语义扩展如下:
ClassAtomNoDash
::
\
[lookahead = c ]
1. 返回 false 。
B.1.2.4 静态语义:CharacterValue
22.2.1.6
的语义扩展如下:
ClassAtomNoDash
::
\
[lookahead = c ]
1. 返回 U+005C (反斜杠) 的数值。
ClassEscape
::
c
ClassControlLetter
1. 令 ch 为由 ClassControlLetter
匹配的代码点。
2. 令 i 为 ch 的数值。
3. 返回 i 除以 32 的余数。
CharacterEscape
:: LegacyOctalEscapeSequence
1. 返回 LegacyOctalEscapeSequence
的 MV (参见 12.9.4.3 )。
B.1.2.5 运行时语义:CompileSubpattern
CompileSubpattern 的语义扩展如下:
Term
::
QuantifiableAssertion
Quantifier
的规则与
Term
::
Atom
Quantifier
相同,但将 QuantifiableAssertion
替换为 Atom 。
Term
::
ExtendedAtom
Quantifier
的规则与
Term
::
Atom
Quantifier
相同,但将 ExtendedAtom 替换为
Atom 。
Term
:: ExtendedAtom
的规则与
Term
:: Atom
相同,但将 ExtendedAtom 替换为
Atom 。
B.1.2.6 运行时语义:CompileAssertion
CompileAssertion 规则适用于
Assertion
::
(?=
Disjunction
)
和
Assertion
::
(?!
Disjunction
)
生产规则,也适用于 QuantifiableAssertion
生产规则,但将 QuantifiableAssertion
替换为 Assertion 。
B.1.2.7 运行时语义:CompileAtom
CompileAtom 规则适用于除
Atom ::
PatternCharacter
外的 ExtendedAtom 生产规则,但将 ExtendedAtom
替换为 Atom 。此外,还增加了以下规则,参数为 direction :
ExtendedAtom
::
\
[lookahead = c ]
1. 令 A 为包含单个字符 \
U+005C(反斜杠)的 CharSet 。
2. 返回 CharacterSetMatcher (rer ,A ,false ,direction )。
ExtendedAtom
:: ExtendedPatternCharacter
1. 令 ch 为由 ExtendedPatternCharacter
表示的字符。
2. 令 A 为包含字符 ch 的一元素 CharSet 。
3. 返回 CharacterSetMatcher (rer ,A ,false ,direction )。
B.1.2.8 运行时语义:CompileToCharSet
22.2.2.9 的语义扩展如下:
以下两条规则替代了 CompileToCharSet 的相应规则。
NonemptyClassRanges
::
ClassAtom
-
ClassAtom
ClassContents
1. 令 A 为第一个 ClassAtom 的 CompileToCharSet ,参数为
rer 。
2. 令 B 为第二个 ClassAtom 的 CompileToCharSet ,参数为
rer 。
3. 令 C 为 ClassContents 的 CompileToCharSet ,参数为
rer 。
4. 令 D 为 CharacterRangeOrUnion (rer ,A ,B )。
5. 返回 D 和 C 的并集。
NonemptyClassRangesNoDash
::
ClassAtomNoDash
-
ClassAtom
ClassContents
1. 令 A 为 ClassAtomNoDash 的
CompileToCharSet ,参数为
rer 。
2. 令 B 为 ClassAtom 的 CompileToCharSet ,参数为
rer 。
3. 令 C 为 ClassContents 的 CompileToCharSet ,参数为
rer 。
4. 令 D 为 CharacterRangeOrUnion (rer ,A ,B )。
5. 返回 D 和 C 的并集。
此外,以下规则被添加到 CompileToCharSet 中。
ClassEscape
::
c
ClassControlLetter
1. 令 cv 为此 ClassEscape emu-nt> 的 CharacterValue 。
2. 令 c 为其字符值为 cv 的字符。
3. 返回包含单个字符 c 的 CharSet 。
ClassAtomNoDash
::
\
[lookahead = c ]
1. 返回包含单个字符 \
U+005C(反斜杠)的 CharSet 。
注
该产生式只能从字符类中 \c
的序列中达到,并且其后不能跟随可接受的控制字符。
B.1.2.8.1 CharacterRangeOrUnion(rer ,A ,
B )
抽象操作 CharacterRangeOrUnion 采用 rer (一个 RegExp 记录 )、A
(一个 CharSet )和 B (一个
CharSet )作为参数,并返回一个 CharSet 。调用时执行以下步骤:
1. 如果 HasEitherUnicodeFlag (rer )为
false ,则
a. 如果 A 和 B 都不包含恰好一个字符,则
i. 令 C 为包含单个字符 -
U+002D(连字符)的
CharSet 。
ii. 返回 CharSets 的并集
A 、B 和 C 。
2. 返回 CharacterRange (A ,
B )。
B.1.2.9 静态语义:ParsePattern(patternText ,u ,v )
22.2.3.4 的语义扩展如下:
抽象操作 ParsePattern 接受参数
patternText (一个 Unicode 代码点序列),u (一个布尔值)和 v (一个布尔值)。调用时执行以下步骤:
1. 如果 v 为 true 且 u 为
true ,则
a. 令 parseResult 为一个包含一个或多个
SyntaxError 对象的 List 。
2. 否则,如果 v 为 true ,则
a. 令 parseResult 为 ParseText (patternText ,
Pattern [+UnicodeMode,
+UnicodeSetsMode, +NamedCaptureGroups] )。
3. 否则,如果 u 为 true ,则
a. 令 parseResult 为 ParseText (patternText ,
Pattern [+UnicodeMode,
~UnicodeSetsMode, +NamedCaptureGroups] )。
4. 否则,
a. 令 parseResult 为 ParseText (patternText ,
Pattern [~UnicodeMode,
~UnicodeSetsMode, ~NamedCaptureGroups] )。
b. 如果 parseResult 是一个 解析节点 且
parseResult
包含一个 GroupName ,则
i. 将 parseResult 设置为 ParseText (patternText ,
Pattern [~UnicodeMode,
~UnicodeSetsMode, +NamedCaptureGroups] )。
5. 返回 parseResult 。
B.2 附加内置属性
当 ECMAScript 宿主 是一个网页浏览器时,标准内置对象的以下附加属性被定义。
B.2.1 全局对象的附加属性
在 表 97
中的条目被添加到 表 6 。
表 97:附加的众所周知的内在对象
B.2.1.1 escape ( string )
此函数是 全局对象
的一个属性。它计算一个新的字符串值,其中某些代码单元已被替换为十六进制转义序列。
当替换数值小于或等于 0x00FF 的代码单元时,使用形式为 %xx
的两位数转义序列。替换数值严格大于 0x00FF 的代码单元时,使用形式为
%uxxxx
的四位数转义序列。
它是 %escape% 内在对象。
它在调用时执行以下步骤:
1. 将 string 设置为 ? ToString (string ).
2. 将 len 设置为 string 的长度。
3. 将 R 设置为空字符串。
4. 将 unescapedSet 设置为 字符串连接 和 ASCII 字符集 和
"@*+-./" 。
5. 将 k 设置为 0。
6. 重复执行,直到 k < len ,
a. 将 C 设置为 string 中索引为 k 的代码单元。
b. 如果 unescapedSet 包含 C ,则
i. 将 S 设置为 C 。
c. 否则,
i. 将 n 设置为 C 的数值。
ii. 如果 n < 256,则
1. 将 hex 设置为 n 的字符串表示,格式为大写十六进制数字。
2. 将 S 设置为 字符串连接 的结果,其中包含
"%" 和 StringPad (hex ,2,"0" ,start )。
iii. 否则,
1. 将 hex 设置为 n 的字符串表示,格式为大写十六进制数字。
2. 将 S 设置为 字符串连接 的结果,其中包含
"%u" 和 StringPad (hex ,4,"0" ,start )。
d. 将 R 设置为 字符串连接
的结果,其中
包含 R 和 S 。
e. 将 k 设置为 k + 1。
7. 返回 R 。
注
此编码部分基于 RFC 1738 中描述的编码,但本标准中指定的整个编码如上所述,不考虑 RFC 1738 的内容。此编码不反映 RFC 3986 对 RFC 1738 所做的更改。
B.2.1.2 unescape ( string )
此函数是 全局对象 的一个属性。它计算一个新的字符串值,其中每个可能由
escape
函数引入的转义序列都被替换为它所代表的代码单元。
它是 %unescape% 内在对象。
它在调用时执行以下步骤:
1. 将 string 设置为 ? ToString (string ).
2. 将 len 设置为 string 的长度。
3. 将 R 设置为空字符串。
4. 将 k 设置为 0。
5. 重复执行,直到 k < len ,
a. 将 C 设置为 string 中索引为 k 的代码单元。
b. 如果 C 是代码单元 0x0025 (百分号),则
i. 将 hexDigits 设置为空字符串。
ii. 将 optionalAdvance 设置为 0。
iii. 如果 k + 5 < len 且
string 中索引为 k + 1 的代码单元是 0x0075 (拉丁小写字母 u),则
1. 将 hexDigits 设置为 string 从
k + 2 到 k + 6 的子字符串。
2. 将 optionalAdvance 设置为 5。
iv. 否则,如果 k + 3 ≤ len ,则
1. 将 hexDigits 设置为 string 从
k + 1 到 k + 3 的子字符串。
2. 将 optionalAdvance 设置为 2。
v. 将 parseResult 设置为 ParseText (StringToCodePoints (hexDigits ),
HexDigits [~Sep] ).
vi. 如果 parseResult 是 解析节点 ,则
1. 将 n 设置为 parseResult 的 MV。
2. 将 C 设置为数值为 n 的代码单元。
3. 将 k 设置为 k +
optionalAdvance 。
6. 返回 R 。
B.2.2 String.prototype 对象的附加属性
B.2.2.1 String.prototype.substr ( start , length )
此方法返回一个子字符串,该子字符串是将 this 值转换为字符串后,从索引 start 开始并延续 length 个代码单元(如果 length 为 undefined 则延续到字符串的结尾)。如果 start 为负数,则将其视为 sourceLength + start ,其中 sourceLength 是字符串的长度。结果是一个字符串值,而不是字符串对象。
调用时执行以下步骤:
1. 让 O 为 ? RequireObjectCoercible (this 值)。
2. 让 S 为 ? ToString (O )。
3. 让 size 为 S 的长度。
4. 让 intStart 为 ? ToIntegerOrInfinity (start )。
5. 如果 intStart = -∞,将 intStart 设为 0。
6. 否则,如果 intStart < 0,将 intStart 设为 max (size + intStart , 0)。
7. 否则,将 intStart 设为 min (intStart , size )。
8. 如果 length 为 undefined ,让 intLength 为 size ;否则让 intLength 为 ? ToIntegerOrInfinity (length )。
9. 将 intLength 设为 clamping intLength 在 0 和 size 之间的结果。
10. 让 intEnd 为 min (intStart + intLength , size )。
11. 返回 substring 从 intStart 到 intEnd 的 S 。
注意
此方法具有通用性;它不要求其 this 值是一个字符串对象。因此它可以被转移到其他类型的对象上使用。
B.2.2.2 String.prototype.anchor ( name )
此方法调用时执行以下步骤:
1. 让 S 为 this 值。
2. 返回 ? CreateHTML (S , "a" ,
"name" , name ).
B.2.2.2.1 CreateHTML ( string , tag ,
attribute , value )
抽象操作 CreateHTML 接受参数 string (一个 ECMAScript 语言值 )、tag (一个字符串)、attribute (一个字符串)和 value (一个 ECMAScript 语言值 ),并返回一个 正常完成包含 的字符串或一个 抛出完成 。调用时执行以下步骤:
1. 让 str 为 ? RequireObjectCoercible (string )。
2. 让 S 为 ? ToString (str )。
3. 让 p1 为 字符串连接 的 "<" 和 tag 。
4. 如果 attribute 不是空字符串,则
a. 让 V 为 ? ToString (value )。
b. 让 escapedV 为与 V 相同的字符串,只是其中每个 0x0022(引号)代码单元都被替换为六个代码单元序列 """ 。
c. 将 p1 设为 字符串连接 的结果,包括:
p1
代码单元 0x0020(空格)
attribute
代码单元 0x003D(等号)
代码单元 0x0022(引号)
escapedV
代码单元 0x0022(引号)
5. 让 p2 为 字符串连接 的 p1 和 ">" 。
6. 让 p3 为 字符串连接 的 p2 和 S 。
7. 让 p4 为 字符串连接 的 p3 、"</" 、tag 和 ">" 。
8. 返回 p4 。
B.2.2.3 String.prototype.big ( )
此方法调用时执行以下步骤:
1. 让 S 为 this 值。
2. 返回 ? CreateHTML (S , "big" ,
"" , "" ).
B.2.2.4 String.prototype.blink ( )
此方法调用时执行以下步骤:
1. 让 S 为 this 值。
2. 返回 ? CreateHTML (S , "blink" ,
"" , "" ).
B.2.2.5 String.prototype.bold ( )
此方法调用时执行以下步骤:
1. 让 S 为 this 值。
2. 返回 ? CreateHTML (S , "b" ,
"" , "" ).
B.2.2.6 String.prototype.fixed ( )
此方法调用时执行以下步骤:
1. 让 S 为 this 值。
2. 返回 ? CreateHTML (S , "tt" ,
"" , "" ).
B.2.2.7 String.prototype.fontcolor ( color )
此方法调用时执行以下步骤:
1. 让 S 为 this 值。
2. 返回 ? CreateHTML (S , "font" ,
"color" , color ).
B.2.2.8 String.prototype.fontsize ( size )
此方法调用时执行以下步骤:
1. 让 S 为 this 值。
2. 返回 ? CreateHTML (S , "font" ,
"size" , size ).
B.2.2.9 String.prototype.italics ( )
此方法调用时执行以下步骤:
1. 让 S 为 this 值。
2. 返回 ? CreateHTML (S , "i" ,
"" , "" ).
B.2.2.10 String.prototype.link ( url )
此方法调用时执行以下步骤:
1. 让 S 为 this 值。
2. 返回 ? CreateHTML (S , "a" ,
"href" , url ).
B.2.2.11 String.prototype.small ( )
此方法调用时执行以下步骤:
1. 让 S 为 this 值。
2. 返回 ? CreateHTML (S , "small" ,
"" , "" ).
B.2.2.12 String.prototype.strike ( )
此方法调用时执行以下步骤:
1. 让 S 为 this 值。
2. 返回 ? CreateHTML (S , "strike" ,
"" , "" ).
B.2.2.13 String.prototype.sub ( )
此方法调用时执行以下步骤:
1. 让 S 为 this 值。
2. 返回 ? CreateHTML (S , "sub" ,
"" , "" ).
B.2.2.14 String.prototype.sup ( )
此方法调用时执行以下步骤:
1. 让 S 为 this 值。
2. 返回 ? CreateHTML (S , "sup" ,
"" , "" ).
B.2.2.15 String.prototype.trimLeft ( )
注意
建议使用属性 "trimStart" 。"trimLeft" 属性主要为兼容旧代码提供。建议在新的 ECMAScript 代码中使用 "trimStart" 属性。
"trimLeft" 属性的初始值为 %String.prototype.trimStart%,定义于 22.1.3.34 。
B.2.2.16 String.prototype.trimRight ( )
注意
建议使用属性 "trimEnd" 。"trimRight" 属性主要为兼容旧代码提供。建议在新的 ECMAScript 代码中使用 "trimEnd" 属性。
"trimRight" 属性的初始值为 %String.prototype.trimEnd%,定义于 22.1.3.33 。
B.2.3 Date.prototype 对象的附加属性
B.2.3.1 Date.prototype.getYear ( )
注意
推荐使用 getFullYear
方法,因为它可以避免“千年虫问题”。
此方法调用时执行以下步骤:
1. 让 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] ).
3. 让 t 为 dateObject .[[DateValue]] 。
4. 如果 t 为 NaN ,返回
NaN 。
5. 返回 YearFromTime (LocalTime (t )) -
1900 𝔽 。
B.2.3.2 Date.prototype.setYear ( year )
注意
推荐使用 setFullYear
方法,因为它可以避免“千年虫问题”。
此方法调用时执行以下步骤:
1. 让 dateObject 为 this 值。
2. 执行 ? RequireInternalSlot (dateObject ,
[[DateValue]] ).
3. 让 t 为 dateObject .[[DateValue]] 。
4. 让 y 为 ? ToNumber (year ).
5. 如果 t 为 NaN ,将 t 设为
+0 𝔽 ;否则,将 t 设为 LocalTime (t )。
6. 让 yyyy 为 MakeFullYear (y )。
7. 让 d 为 MakeDay (yyyy , MonthFromTime (t ),
DateFromTime (t ))。
8. 让 date 为 MakeDate (d , TimeWithinDay (t ))。
9. 让 u 为 TimeClip (UTC (date ))。
10. 将 dateObject .[[DateValue]]
设为 u 。
11. 返回 u 。
B.2.3.3 Date.prototype.toGMTString ( )
注意
推荐使用 toUTCString
方法。此方法主要为兼容旧代码而提供。
"toGMTString" 属性的初始值为 %Date.prototype.toUTCString%,定义于 21.4.4.43 。
B.2.4 RegExp.prototype 对象的附加属性
B.2.4.1 RegExp.prototype.compile ( pattern , flags )
此方法调用时执行以下步骤:
1. 让 O 为 this 值。
2. 执行 ? RequireInternalSlot (O ,
[[RegExpMatcher]] ).
3. 如果 pattern 是一个对象
并且 pattern 具有 [[RegExpMatcher]] 内部槽,则
a. 如果 flags 不为 undefined ,
抛出 TypeError 异常。
b. 让 P 为 pattern .[[OriginalSource]] 。
c. 让 F 为 pattern .[[OriginalFlags]] 。
4. 否则,
a. 让 P 为 pattern 。
b. 让 F 为 flags 。
5. 返回 ? RegExpInitialize (O , P , F ).
注意
此方法完全重新初始化 this 值的 RegExp 对象,使用新的模式和标志。实现可能会将此方法的使用解释为对结果 RegExp 对象将被多次使用的断言,因此是额外优化的候选对象。
B.3 其他附加功能
B.3.1 带标签的函数声明
在 ECMAScript 2015 之前,LabelledStatement 的规范不允许将语句标签与
FunctionDeclaration 关联。然而,带标签的
FunctionDeclaration 是 非严格模式代码 的一个允许扩展,并且大多数浏览器托管的 ECMAScript
实现支持该扩展。在 ECMAScript 2015 及以后版本中,LabelledStatement 的语法生成规则允许将
FunctionDeclaration 作为 LabelledItem 使用,但
14.13.1
包含一条早期错误规则,如果发生这种情况将产生语法错误。该规则在新增的 高亮显示 文本中进行了修改:
LabelledItem
: FunctionDeclaration
如果任何源文本 匹配此生成规则的 严格模式代码 ,则为语法错误。
注
B.3.2 块级函数声明的网页遗留兼容性语义
在 ECMAScript 2015 之前,ECMAScript 规范未定义 FunctionDeclaration 作为 Block 语句的 StatementList
的一个元素。然而,对这种形式的 FunctionDeclaration
的支持是一个允许的扩展,大多数浏览器托管的 ECMAScript 实现允许这种声明。不幸的是,这些声明的语义在这些实现之间存在差异。由于这些语义差异,现有的网页 ECMAScript
源文本 只在浏览器实现之间是可移植的,如果使用仅依赖于这些声明的所有浏览器实现的语义交集。以下是落在这些交集语义中的用例:
在单个块中声明并仅在其中引用一个函数。
在单个 Block
中声明并可能使用一个函数,但也被不在该块中的内部函数定义引用。
在单个块中声明并可能使用一个函数,但在后续块中也被引用。
第一个用例与 ECMAScript 2015 提供的块级函数声明的语义是互操作的。任何使用该用例的现有 ECMAScript 源文本 将按照 ECMAScript 2015
规范中的块级函数声明语义运行,参见条款 10 、14 和
15 a> 。
对于第二和第三个用例,ECMAScript 2015 的互操作性要求对条款 10 、条款
15 、条款
19.2.1 和条款 16.1.7 的语义进行扩展。
如果 ECMAScript 实现具有报告诊断警告消息的机制,当代码中包含适用这些兼容性语义且与非兼容语义引入可观察差异的 FunctionDeclaration
时,应产生警告。例如,如果一个 var 绑定没有被引入,因为它的引入将创建一个 早期错误 ,则不应产生警告消息。
B.3.2.1 对 FunctionDeclarationInstantiation 的更改
在 FunctionDeclarationInstantiation
过程中,以下步骤会替代步骤 29 :
29. 如果 strict 为 false ,则
a. 对于每个直接包含在 FunctionDeclaration
f 中的 StatementList 、Block 、CaseClause 或
DefaultClause 中的
f ,执行以下操作
i. 让 F 为 StringValue
的 BindingIdentifier 。
ii. 如果将 FunctionDeclaration
f 替换为一个具有 F 作为 VariableStatement 的
BindingIdentifier
的话不会对 func 产生任何早期错误,并且 parameterNames 不包含 F ,则
1. 注意:只有在 F 既不是
VarDeclaredName,也不是形式参数的名称,或者不是另一个 FunctionDeclaration
时,才在此实例化 F 的 var 绑定。
2. 如果 instantiatedVarNames 不包含 F
并且 F 不是 "arguments" ,则
a. 执行
! varEnv .CreateMutableBinding(F , false )。
b. 执行
! varEnv .InitializeBinding(F ,
undefined )。
c. 将 F 添加到
instantiatedVarNames 中。
3. 当 FunctionDeclaration
f 被评估时,执行以下步骤以替代 FunctionDeclaration
的 Evaluation 算法,参见
15.2.6 :
a. 让 fenv 为当前执行上下文的 VariableEnvironment。
b. 让 benv 为当前执行上下文的 LexicalEnvironment。
c. 让 fobj 为
! benv .GetBindingValue(F , false )。
d. 执行
! fenv .SetMutableBinding(F , fobj ,
false )。
e. 返回 unused 。
B.3.2.2 对 GlobalDeclarationInstantiation 的更改
在 GlobalDeclarationInstantiation
过程中,以下步骤会替代步骤 12 :
12. 执行以下步骤:
a. 让 strict 为 IsStrict 的
script 。
b. 如果 strict 为 false ,则
i. 让 declaredFunctionOrVarNames 为 list-concatenation 的
declaredFunctionNames 和 declaredVarNames 。
ii. 对于每个直接包含在 FunctionDeclaration
f 中的 StatementList 、Block 、CaseClause
或 DefaultClause 中的
f ,执行以下操作
1. 让 F 为 StringValue
的 BindingIdentifier 。
2. 如果将 FunctionDeclaration
f 替换为一个具有 F 作为 VariableStatement
的 BindingIdentifier
的话不会对 script 产生任何早期错误,则
a. 如果
env .HasLexicalDeclaration(F ) 为 false ,则
i. 让 fnDefinable 为
? env .CanDeclareGlobalVar(F )。
ii. 如果 fnDefinable 为
true ,则
i. 注意:只有在 F 既不是
VarDeclaredName,也不是另一个 FunctionDeclaration
的名称时,才在此实例化 F 的 var 绑定。
ii. 如果 declaredFunctionOrVarNames
不包含 F ,则
i. 执行
? env .CreateGlobalVarBinding(F ,
false )。
ii. 将 F 添加到
declaredFunctionOrVarNames 中。
iii. 当 FunctionDeclaration
f 被评估时,执行以下步骤以替代 FunctionDeclaration
的 Evaluation
算法,参见 15.2.6 :
i. 让 genv 为当前执行上下文的
VariableEnvironment。
ii. 让 benv 为当前执行上下文的
LexicalEnvironment。
iii. 让 fobj 为
! benv .GetBindingValue(F ,
false )。
iv. 执行 ? genv .SetMutableBinding (F ,
fobj , false )。
v. 返回 unused 。
B.3.2.3 对 EvalDeclarationInstantiation 的更改
在 EvalDeclarationInstantiation
中,以下步骤会替代步骤 13 :
13. 如果 strict 为 false ,则
a. 让 declaredFunctionOrVarNames 为 list-concatenation
的 declaredFunctionNames 和 declaredVarNames 。
b. 对于每个直接包含在 FunctionDeclaration
f 中的 StatementList 的
Block ,
CaseClause 或 DefaultClause 中,
对 body 执行以下操作
i. 让 F 为 StringValue
的 BindingIdentifier
的值。
ii. 如果将 FunctionDeclaration
f 替换为一个将 F 作为 BindingIdentifier
的 VariableStatement
不会对 body 产生任何 Early Errors,则
1. 让 bindingExists 为
false 。
2. 让 thisEnv 为 lexEnv 。
3. Assert :以下循环将终止。
4. 重复,直到 thisEnv 为
varEnv ,
a. 如果 thisEnv 不是一个对象 Environment
Record ,则
i. 如果
! thisEnv .HasBinding(F ) 为 true ,则
i. 让 bindingExists 为
true 。
b. 将 thisEnv 设置为
thisEnv .[[OuterEnv]] 。
5. 如果 bindingExists 为
false 且 varEnv 为 Global Environment
Record ,则
a. 如果
varEnv .HasLexicalDeclaration(F ) 为 false ,则
i. 让 fnDefinable 为
? varEnv .CanDeclareGlobalVar(F ).
b. 否则,
i. 让 fnDefinable 为
false 。
6. 否则,
a. 让 fnDefinable 为
true 。
7. 如果 bindingExists 为
false 且 fnDefinable 为 true ,则
a. 如果 declaredFunctionOrVarNames 不包含
F ,则
i. 如果 varEnv 为 Global
Environment Record ,则
i. 执行
? varEnv .CreateGlobalVarBinding(F ,
true ).
ii. 否则,
i. 让 bindingExists 为
! varEnv .HasBinding(F ).
ii. 如果 bindingExists 为
false ,则
i. 执行
! varEnv .CreateMutableBinding(F ,
true ).
ii. 执行
! varEnv .InitializeBinding(F ,
undefined ).
iii. 将 F 附加到
declaredFunctionOrVarNames 中。
b. 当 FunctionDeclaration
f 被评估时,执行以下步骤来替代 FunctionDeclaration
Evaluation
算法中的 15.2.6 :
i. 让 genv 为 正在执行的
执行上下文 的 VariableEnvironment。
ii. 让 benv 为 正在执行的
执行上下文 的 LexicalEnvironment。
iii. 让 fobj 为
! benv .GetBindingValue(F ,
false ).
iv. 执行 ? genv .SetMutableBinding (F ,
fobj , false ).
v. 返回 unused 。
B.3.2.4 对块静态语义的更改:早期错误
在 14.2.1
中,以下规则被修改,添加了突出显示的 文本:
Block :
{
StatementList
}
B.3.2.5 对 switch
语句静态语义的更改:早期错误
在 14.12.1
中,以下规则被修改,添加了突出显示的 文本:
SwitchStatement
:
switch
(
Expression
)
CaseBlock
B.3.2.6 对 BlockDeclarationInstantiation 的更改
在 BlockDeclarationInstantiation
中,以下步骤代替步骤 3.a.ii.1
执行:
1. 如果 ! env .HasBinding(dn ) 为
false ,则
a. 执行
! env .CreateMutableBinding(dn , false )。
在 BlockDeclarationInstantiation
中,以下步骤代替步骤 3.b.iii
执行:
iii. 执行以下步骤:
1. 如果 fn 在 env 中的绑定是一个
未初始化的绑定,则
a. 执行
! env .InitializeBinding(fn , fo )。
2. 否则,
a. 断言 :d 是一个
FunctionDeclaration 。
b. 执行
! 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
的语义包括 Web
传统兼容性语义 中指定的内容。
B.3.4 Catch 块中的 VariableStatements
子条款 14.15.1
的内容被以下内容替换:
Catch :
catch
(
CatchParameter
)
Block
注
Block 的
Catch 子句中可能
包含绑定了与 CatchParameter
相同名称的 var
声明。在运行时,这些绑定会在 VariableDeclarationEnvironment 中实例化。
它们不会遮蔽由 CatchParameter
引入的同名绑定,因此这些 var
声明的 Initializer 将赋值给相应的捕获参数,而不是
var
绑定。
这种修改后的行为同样适用于在 直接 eval
调用中引入的 var
和 function
声明,这些调用包含在 Block 中的 Catch 子句中。这一变化通过修改 19.2.1.3 的算法实现,具体如下:
步骤 3.d.i.2.a.i
被替换为:
i. 如果 thisEnv 不是 Environment
Record 用于
Catch 子句,
抛出 SyntaxError 异常。
步骤 13.b.ii.4.a.i.i
被替换为:
i. 如果 thisEnv 不是 Environment
Record 用于
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
1. 返回ContainsDuplicateLabels
对Statement
的调用,参数为labelSet 。
静态语义 中的ContainsUndefinedBreakTarget
在8.3.2
被扩展为以下内容:
ForInOfStatement
:
for
(
var
BindingIdentifier
Initializer
in
Expression
)
Statement
1. 返回ContainsUndefinedBreakTarget
对Statement
的调用,参数为labelSet 。
静态语义 中的ContainsUndefinedContinueTarget
在8.3.3
被扩展为以下内容:
ForInOfStatement
:
for
(
var
BindingIdentifier
Initializer
in
Expression
)
Statement
1. 返回ContainsUndefinedContinueTarget
对Statement
的调用,参数为labelSet 。
B.3.6 [[IsHTMLDDA]] 内部槽
一个[[IsHTMLDDA]] 内部槽 可能存在于宿主定义的 对象上。具有[[IsHTMLDDA]] 内部槽的对象在ToBoolean 和 IsLooselyEqual 抽象操作 中表现得像undefined ,并且在用作typeof
操作符 的操作数时也是如此。
注
具有[[IsHTMLDDA]] 内部槽的对象不会由本规范创建。然而,document.all
对象 在网页浏览器中是一个具有此槽的宿主定义的 异域对象
,存在是为了网页兼容性目的。没有其他已知的此类对象,除document.all
外,其他实现不应创建这种对象。
B.3.6.1 对ToBoolean的更改
以下步骤替代3 中的
ToBoolean 步骤:
3. 如果argument 是一个对象
并且argument 具有[[IsHTMLDDA]] 内部槽,则返回
false 。
B.3.6.2 对IsLooselyEqual的更改
以下步骤替代4
中的IsLooselyEqual 步骤:
4. 执行以下步骤:
a. 如果x 是一个对象 ,
x 具有[[IsHTMLDDA]] 内部槽,并且y 是
undefined 或 null ,则返回
true 。
b. 如果x 是 undefined 或
null ,y 是一个对象 ,并且
y 具有[[IsHTMLDDA]] 内部槽,则返回
true 。
B.3.6.3 对typeof
操作符的更改
以下步骤替代12 中的
typeof 评估语义:
12. 如果val 具有[[IsHTMLDDA]]
内部槽,则返回 "undefined" 。
B.3.7 HostMakeJobCallback中的非默认行为
HostMakeJobCallback 抽象操作允许
宿主 (即网页浏览器)指定非默认行为。
B.3.8 HostEnsureCanAddPrivateElement中的非默认行为
HostEnsureCanAddPrivateElement
抽象操作允许宿主 (即网页浏览器)指定非默认行为。
C ECMAScript 的严格模式
严格模式的限制和例外
D 宿主分层点
参见 4.2 关于
宿主 .
D.1 宿主钩子
宿主调用作业回调 (...)
宿主入队清理最终化注册表作业 (...)
宿主入队通用作业 (...)
宿主入队承诺作业 (...)
宿主入队超时作业 (...)
宿主确保可以编译字符串 (...)
宿主完成导入元数据 (...)
宿主获取导入元数据属性 (...)
宿主增长共享数组缓冲区 (...)
宿主是否有源文本可用 (...)
宿主加载导入模块 (...)
宿主创建作业回调 (...)
宿主承诺拒绝跟踪器 (...)
宿主调整数组缓冲区大小 (...)
初始化宿主定义的领域 (...)
D.2 宿主定义的字段
[[HostDefined]] 在 领域记录 : 参见 表 24 .
[[HostDefined]] 在 脚本记录 : 参见 表
40 .
[[HostDefined]] 在 模块记录 : 参见
表 41 .
[[HostDefined]] 在 作业回调记录 : 参见
表 28 .
[[HostSynchronizesWith]] 在候选执行: 参见 表 96 .
[[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.15 -9.1.1.4.18
第五版和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
偏移表示,使用本地时区。第五版 5.1 错误地声明缺失的时区应解释为 "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" 属性值中的任何 LineTerminator 代码点必须使用转义序列表示。第五版 5.1 仅要求转义 /
。
22.2.6.8 , 22.2.6.11 :
在以前的版本中,String.prototype.match
和
String.prototype.replace
的规范在模式参数为一个 RegExp 值且 global
标志被设置的情况下是不正确的。以前的规范指出,对于每次尝试匹配模式,如果 lastIndex
没有变化,应将其递增 1。正确的行为是仅当模式匹配了空字符串时才将
lastIndex
递增 1。
23.1.3.30 : 以前的版本未指定由
comparefn 返回的 NaN 值如何被 Array.prototype.sort
解释。ECMAScript 2015
规定这样的值被视为 +0 𝔽 从 comparefn 返回。ECMAScript 2015 还规定 ToNumber 应用于
comparefn 返回的结果。在以前的版本中,comparefn 结果为非数字值的效果是 实现定义的 。实际上,实施调用 ToNumber 。
F 介绍与以前版本不兼容的新增内容和更改
6.2.5 : 在 ECMAScript
2015 中,函数调用不允许返回 引用记录 。
7.1.4.1 : 在
ECMAScript 2015 中,ToNumber 应用于字符串值现在可以识别和转换 二进制整数字面量 和 八进制整数字面量
数字字符串。在以前的版本中,这些字符串会被转换为 NaN 。
9.3 : 在 ECMAScript 2018 中,模板对象是基于 解析节点 (源位置)规范化的,而不是像以前版本中那样在 范围 内所有模板字面量或标记模板的所有出现。
12.2 : 在 ECMAScript 2016 中,规定必须使用 Unicode
8.0.0 或更高版本,而 ECMAScript 2015 中规定必须使用 Unicode 5.1。特别是,这导致 U+180E 蒙古语元音分隔符,它在
Space_Separator
(Zs
)类别中,因此在 ECMAScript 2015 中被视为空白字符,被移到
Format
(Cf
)类别(截至 Unicode
6.3.0)。这导致对空白字符敏感的方法表现不同。例如,"\u180E".trim().length
在以前的版本中为 0
,但在 ECMAScript 2016
及以后版本中为 1
。此外,ECMAScript 2017 规定必须始终使用最新版本的 Unicode 标准。
12.7 : 在 ECMAScript 2015 中,有效的 标识符名称 的代码点是根据 Unicode 属性
“ID_Start” 和 “ID_Continue” 指定的。在以前的版本中,有效的 标识符名称 或 标识符 代码点是通过列举各种 Unicode 代码点类别来指定的。
12.10.1 : 在
ECMAScript 2015 中,如果 do-while 语句缺少分号,自动分号插入会在其末尾添加一个分号。这一更改使规范与大多数现有实现的实际行为一致。
13.2.5.1 :
在 ECMAScript 2015 中,在对象初始化器中具有重复属性名称不再是 早期错误 。
13.15.1 :
在 ECMAScript 2015 中,包含对不可变绑定(例如 函数表达式 的函数名称)的赋值的严格模式代码不会产生 早期错误 。相反,它会产生运行时错误。
14.2 : 在
ECMAScript 2015 中,一个以 token let 开头,后跟输入元素 行终止符 然后是 标识符 的 语句列表 是一个 词法声明 的开始。在以前的版本中,自动分号插入会在 标识符 输入元素之前总是插入一个分号。
14.5 : 在 ECMAScript 2015 中,一个以 token
let
开头,后跟 token [
的 语句列表项 是一个 词法声明 的开始。在以前的版本中,这样的序列会是一个 表达式语句 的开始。
14.6.2 : 在
ECMAScript 2015 中,一个 if
语句 的正常结果从不为 empty 。如果没有 语句 部分被评估,或者如果评估的 语句 部分产生的 正常完成包含
empty ,则 if
语句 的结果为 undefined 。
14.7 : 在 ECMAScript 2015 中,如果 for
语句的 (
token 后面紧跟着 let [
,则 let
被视为 词法声明 的开始。在以前的版本中,这种 token 序列会被视为
表达式 的开始。
14.7 : 在 ECMAScript 2015 中,如果 for-in
语句的 ( token 后面紧跟着 let [
,则 let
被视为 ForDeclaration 的开始。在以前的版本中,这种 token 序列会被视为
左侧表达式 的开始。
14.7 : 在 ECMAScript 2015
之前,初始化表达式可以作为 变量声明 的一部分出现在 in
关键字 之前。在 ECMAScript 2015
中,相同位置的 ForBinding
不允许出现这样的初始化器。在 ECMAScript 2017 中,这种初始化器仅在 非严格模式代码 中被允许。
14.7 : 在 ECMAScript 2015 中,评估
迭代语句 的结果从不为
正常完成 其 [[Value]] 为 empty 。如果 语句 部分未被评估,或者最终评估的 迭代语句 的 语句 部分产生的 正常完成 其 [[Value]] 为 empty ,则评估 迭代语句 的结果是一个 正常完成 其 [[Value]] 为 undefined 。
14.11.2 :
在 ECMAScript 2015 中,评估 WithStatement 的结果从不为 正常完成 其 [[Value]] 为 empty 。如果评估 语句 部分的 WithStatement 产生了 正常完成 其 [[Value]] 为 empty ,则评估 WithStatement 的结果是一个 正常完成 其 [[Value]] 为 undefined 。
14.12.4 :
在 ECMAScript 2015 中,评估 SwitchStatement 的结果从不为 正常完成 其 [[Value]] 为 empty 。如果评估 CaseBlock 部分的 SwitchStatement 产生了 正常完成 其 [[Value]] 为 empty ,则评估 SwitchStatement 的结果是一个 正常完成 其 [[Value]] 为 undefined 。
14.15 : 在 ECMAScript 2015 中,早期错误 如果
Catch 子句包含一个
var
声明,其标识符与出现为 标识符 的 Catch 子句参数相同。在以前的版本中,这样的变量声明会在封闭的变量环境中实例化,但声明的
初始化器 值会被赋给 Catch 参数。
14.15 , 19.2.1.3 : 在 ECMAScript
2015 中,如果 Catch 子句评估一个非严格模式的
eval
,其 eval 代码中包含一个 var
或 FunctionDeclaration
声明,这些声明绑定了与出现为 标识符 相同的 Catch 子句参数,则会抛出一个运行时
SyntaxError 。
14.15.3 :
在 ECMAScript 2015 中,TryStatement 的结果从不为
empty 。如果 块 部分的 TryStatement 评估为一个 正常完成包含
empty ,则 TryStatement 的结果是
undefined 。如果 块 部分的 < emu-nt id="_ref_23187">TryStatement 评估为一个 抛出完成 并且其 Catch 部分评估为一个 正常完成包含
empty ,则如果没有 Finally 子句或其 Finally 子句评估为一个 empty
正常完成 ,则 TryStatement 的结果为
undefined 。
15.4.5
在 ECMAScript 2015 中,作为 [[Get]] 或 [[Set]] 属性值的 访问器属性 的 ObjectLiteral 中创建的 函数对象 不是 构造函数
并且它们没有 "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 中,[[Prototype]] 内部插槽的 NativeError 构造函数 是
Error 构造函数 。在以前的版本中,它是 Function
原型对象 。
21.4.4 在
ECMAScript 2015 中,Date 原型对象 不是一个
Date 实例。在以前的版本中,它是一个 Date 实例,其 TimeValue 为 NaN 。
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.4.4 、27.6.3.6 : 在 ECMAScript 2019
中,await
队列中的 任务 数量减少,这可能会导致 then()
调用和
await
表达式之间的解析顺序出现可观察到的差异。
G 说明
本规范在 GitHub 上以一种称为 Ecmarkup 的纯文本格式编写。Ecmarkup 是一种 HTML 和 Markdown
方言,提供了一个框架和工具集,用于以纯文本编写 ECMAScript 规范,并将规范处理成符合本文件编辑规范的全面 HTML 渲染。Ecmarkup 构建在并集成了多种其他格式和技术,包括用于定义语法的 Grammarkdown 和用于编写算法步骤的 Ecmarkdown 。本规范的 PDF 渲染通过将 HTML 渲染打印为 PDF 来生成。
本规范的早期版本使用 Word 编写——本版本的 Ecmarkup 源文本是通过使用自动转换工具将 ECMAScript 2015 Word 文档转换为 Ecmarkup 生成的。
H 参考文献
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 表情符号 ,可在 <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 > 查阅
I 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
© 2024 Ecma International
By obtaining and/or copying this work, you (the licensee) agree that you have read, understood, and will
comply
with the following terms and conditions.
Permission under Ecma’s copyright to copy, modify, prepare derivative works of, and distribute this work,
with
or without modification, for any purpose and without fee or royalty is hereby granted, provided that you
include
the following on ALL copies of the work or portions thereof, including modifications:
(i) The full text of this COPYRIGHT NOTICE AND COPYRIGHT LICENSE in a location viewable to users of the
redistributed or derivative work.
(ii) Any pre-existing intellectual property disclaimers, notices, or terms and conditions. If none
exist,
the Ecma alternative copyright notice should be included.
(iii) Notice of any changes or modifications, through a copyright statement on the document such as
“This
document includes material copied from or derived from [title and URI of the Ecma document]. Copyright ©
Ecma
International.”
Disclaimers
THIS WORK IS PROVIDED “AS IS,” AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED,
INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT
THE
USE OF THE DOCUMENT WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT
OF
ANY USE OF THE DOCUMENT.
The name and trademarks of copyright holders may NOT be used in advertising or publicity pertaining to the
work
without specific, written prior permission. Title to copyright in this work will at all times remain with
copyright holders.
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.