ECMAScript® 2024 语言规范

关于本规范

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

本文档可以作为单页多页查看。

为此规范做贡献

此规范在GitHub上由ECMAScript社区的帮助下开发。有多种方式可以为此规范的发展做出贡献:

有关如何创建此文档的更多信息,请参阅colophon

导言

此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.valuesObject.entriesObject.getOwnPropertyDescriptors

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

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

ECMAScript 2020,第11版,引入了字符串的matchAll方法,用于生成全局正则表达式匹配对象的迭代器;import()语法,用于动态异步导入模块;BigInt,一种新的数字原始类型,用于处理任意精度的整数Promise.allSettled,一种新的Promise组合器,不会短路;globalThis,一种通用的全局this值访问方式;专用的export * as ns from 'module'语法,用于模块内;增加了for-in枚举顺序的标准化;import.meta,一个由宿主填充的对象,包含关于模块的上下文信息;以及为处理“nullish”值(undefinednull)引入的两个新语法特性:nullish合并,一个值选择操作符;以及可选链,一个属性访问和函数调用操作符,当要访问/调用的值为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.hasOwnObject.prototype.hasOwnProperty的便捷替代。

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

ECMAScript 2024,第15版,增加了调整和转移ArrayBuffers和SharedArrayBuffers大小的功能;添加了用于创建具有更高级功能的字符串集的RegExp/v标志;引入了用于构建Promise的便捷方法Promise.withResolvers、用于数据聚合的Object.groupByMap.groupBy方法、用于异步等待共享内存更改的Atomics.waitAsync方法,以及用于检查和确保字符串仅包含格式良好的Unicode的String.prototype.isWellFormedString.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-2019IEEE 浮点算术标准

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

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

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

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

4 概述

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

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

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

ECMAScript 最初设计为一种 Web 脚本语言,提供一种机制来在浏览器中使网页生动起来,并作为基于 Web 的客户端-服务器架构的一部分执行服务器计算。ECMAScript 现在用于为各种 宿主环境 提供核心脚本功能。因此,本文件中规定的核心语言与任何特定的 宿主环境 无关。

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

4.1 Web脚本

Web浏览器为客户端计算提供了一个ECMAScript 宿主环境,包括表示窗口、菜单、弹出窗口、对话框、文本区域、锚点、框架、历史记录、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 代码分配不同值给该属性的操作都会失败。属性是包含其他对象、原始值函数 的容器。原始值是以下内置类型之一的成员:UndefinedNullBooleanNumberBigIntStringSymbol;对象是内置类型 Object 的成员;函数是可调用对象。通过属性与对象关联的函数称为 方法

ECMAScript 定义了一组 内置对象,完善了 ECMAScript 实体的定义。这些内置对象包括 全局对象;对语言的 运行时语义 基本的对象,包括 ObjectFunctionBooleanSymbol 及各种 Error 对象;表示和操作数值的对象,包括 MathNumberDate;处理文本的对象 StringRegExp;值的索引集合的对象,包括 Array 和九种不同类型的元素具有特定数值表示的 Typed Arrays;键控集合,包括 MapSet 对象;支持结构化数据的对象,包括 JSON 对象、ArrayBufferSharedArrayBufferDataView;支持控制抽象的对象,包括生成器函数和 Promise 对象;以及反射对象,包括 ProxyReflect

ECMAScript 还定义了一组内置 运算符。ECMAScript 运算符包括各种一元运算符、乘法运算符、加法运算符、位移运算符、关系运算符、相等运算符、二进制位运算符、二进制逻辑运算符、赋值运算符和逗号运算符。

大型 ECMAScript 程序由 模块 支持,允许程序划分为多个语句和声明的序列。每个模块明确标识其使用的需要由其他模块提供的声明,以及哪些声明可供其他模块使用。

ECMAScript 语法故意类似于 Java 语法。ECMAScript 语法被放宽,以使其作为一种易于使用的脚本语言。例如,变量不需要声明其类型,属性也没有关联类型,定义的函数也不需要在调用之前出现在文本上。

4.3.1 对象

尽管 ECMAScript 包含类定义的语法,但 ECMAScript 对象并非如 C++、Smalltalk 或 Java 中的类为基础。相反,对象可以通过多种方式创建,包括字面量表示法或 构造函数,这些构造函数创建对象,然后通过为其属性分配初始值来初始化全部或部分对象。每个 构造函数 都是一个具有名为 "prototype" 属性的函数,该属性用于实现 基于原型的继承共享属性。对象通过在 new 表达式中使用 构造函数 创建;例如,new Date(2009, 11) 创建一个新的 Date 对象。不使用 new 调用 构造函数 会产生不同的结果,这取决于 构造函数。例如,Date() 生成当前日期和时间的字符串表示,而不是对象。

每个由 构造函数 创建的对象都有一个隐式引用(称为对象的 原型),指向其 构造函数"prototype" 属性的值。此外,原型可能有一个非 null 的隐式引用指向其原型,依此类推;这称为 原型链。当引用对象中的属性时,该引用是指向原型链中第一个包含该名称属性的对象中的属性。换句话说,首先检查直接提到的对象是否包含该属性;如果该对象包含命名属性,则该引用指向的就是该属性;如果该对象不包含命名属性,则接下来检查该对象的原型;依此类推。

图 1:对象/原型关系
许多框和箭头的图片。

在基于类的面向对象语言中,通常状态由实例承载,方法由类承载,并且继承仅限于结构和行为。而在 ECMAScript 中,状态和方法由对象承载,而结构、行为和状态都是继承的。

所有不直接包含其原型所包含的特定属性的对象共享该属性及其值。图 1 说明了这一点:

CF 是一个 构造函数(也是一个对象)。通过使用 new 表达式创建了五个对象:cf1cf2cf3cf4cf5。这些对象每个都包含名为 "q1""q2" 的属性。虚线表示隐式原型关系;例如,cf3 的原型是 CFp构造函数 CF 本身有两个属性,分别为 "P1""P2",它们在 CFpcf1cf2cf3cf4cf5 中不可见。CFp 中名为 "CFP1" 的属性由 cf1cf2cf3cf4cf5 共享(但不包括 CF),以及 CFp 的隐式原型链中除 "q1""q2""CFP1" 之外的任何属性。注意,CFCFp 之间没有隐式原型链接。

与大多数基于类的对象语言不同,可以通过分配值动态地向对象添加属性。也就是说,构造函数 不需要命名或分配所有或任何构造对象的属性。在上图中,可以通过向 CFp 中的属性分配新值,为 cf1cf2cf3cf4cf5 添加一个新的共享属性。

尽管 ECMAScript 对象本质上不是基于类的,但根据 构造函数、原型对象和方法的共同模式定义类样抽象通常是方便的。ECMAScript 内置对象本身遵循这样的类样模式。从 ECMAScript 2015 开始,ECMAScript 语言包括语法类定义,允许程序员简洁地定义符合内置对象使用的相同类样抽象模式的对象。

4.3.2 ECMAScript 的严格变体

ECMAScript 语言认识到某些用户可能希望限制其使用语言中某些功能的可能性。他们可能出于安全考虑,避免他们认为容易出错的功能,获得增强的错误检查,或出于其他原因。为了支持这种可能性,ECMAScript 定义了语言的严格变体。语言的严格变体排除了一些常规 ECMAScript 语言的特定语法和语义特性,并修改了某些特性的详细语义。严格变体还指定了在非严格形式的语言未指定为错误的情况下必须通过抛出错误异常来报告的其他错误条件。

ECMAScript 的严格变体通常称为语言的严格模式。严格模式的选择和 ECMAScript 严格模式语法和语义的使用明确在单个 ECMAScript 源文本 单元级别进行,如 11.2.2 中所述。由于在语法源文本单元级别选择严格模式,因此严格模式仅对该源文本单元内具有局部效果的限制。严格模式不会限制或修改必须在多个源文本单元之间一致操作的 ECMAScript 语义。完整的 ECMAScript 程序可以由严格模式和非严格模式 ECMAScript 源文本 单元组成。在这种情况下,严格模式仅在实际执行在严格模式源文本单元中定义的代码时才适用。

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

4.4 术语和定义

在本文件中,适用以下术语和定义。

4.4.1 实现近似 (implementation-approximated)

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

4.4.2 实现定义 (implementation-defined)

一个 实现定义 设施是由外部来源全部或部分定义的。

4.4.3 宿主定义 (host-defined)

实现定义 相同。

编辑说明,参见 4.2 条款。

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 类型 的成员

只有两个布尔值,truefalse

4.4.18 Boolean 类型 (Boolean type)

由原始值 truefalse 组成的类型

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)

内置对象,是一个函数

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

4.4.36 内置构造函数 (built-in constructor)

内置函数,是一个 构造函数

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

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 章中。它定义了一组生成式,从 目标符号 InputElementDivInputElementTemplateTailInputElementRegExpInputElementRegExpOrTemplateTailInputElementHashbangOrRegExp 开始,描述了如何将这些代码点的序列转换为输入元素的序列。

除空白和注释外的输入元素构成 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)。它定义了一组生成式,从两个可选的 目标符号 ScriptModule 开始,描述了标记序列如何形成 ECMAScript 程序的句法上正确的独立组件。

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

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

解析器的每次调用都会实例化新的解析节点,并且在解析相同源文本时永不重用。解析节点被认为是相同的解析节点,当且仅当它们表示相同的源文本范围,是相同文法符号的实例,并且是由同一次解析器调用生成的。

注 1

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

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

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

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

句法文法的生成式通过使用一个冒号 “:” 作为标点符号来区分。

第13节第16节 中所述的句法文法并不完全说明哪些标记序列被接受为正确的 ECMAScript ScriptModule。某些附加的标记序列也被接受,即那些如果只在某些地方添加分号(如在行终止符之前)就能描述的序列。此外,如果行终止符出现在某些“尴尬”的地方,则由文法描述的某些标记序列也不被认为是可接受的。

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

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

5.1.5 语法标记

5.1.5.1 终结符号

在ECMAScript语法中,一些终结符号显示为固定宽度字体。这些符号应当按照书写的样子准确出现在源文本中。以这种方式指定的所有终结符号码点都应被理解为来自基本拉丁块的适当Unicode码点,而不是来自其他Unicode范围的类似看起来的码点。终结符号中的一个码点不能通过\ UnicodeEscapeSequence来表达。

在其终结符号是单个Unicode码点的语法中(即,词汇、RegExp和数值字符串语法),连续的多个固定宽度码点出现在一个生产中,是一种简单的速记,用于表示相同的码点序列,写作独立的终结符号。

例如,产生式:

HexIntegerLiteral :: 0x HexDigits

是以下的简写形式:

HexIntegerLiteral :: 0 x HexDigits

相比之下,在句法语法中,连续的固定宽度码点构成一个单独的终结符号。

终结符号还有其他两种形式:

5.1.5.2 非终结符号与生产规则

非终结符号显示为斜体类型。非终结(也称为“产生式”)的定义是由被定义的非终结名称开始,后面跟着一个或多个冒号(冒号的数量表示生产所属的语法)。然后,非终结的一个或多个备选右侧在后续行中跟随。例如,句法定义:

WhileStatement : while ( Expression ) Statement

说明非终结WhileStatement 表示关键字while,后跟一个左括号,然后是一个Expression, 后跟一个右括号,然后是一个Statement。这里出现的ExpressionStatement本身也是非终结。作为另一个例子,句法定义:

ArgumentList : AssignmentExpression ArgumentList , AssignmentExpression

说明一个ArgumentList 可能代表一个单独的AssignmentExpression或一个ArgumentList, 后跟一个逗号,然后是一个AssignmentExpression。 这个ArgumentList的定义是递归的,即它是以自身为基础定义的。结果是,一个ArgumentList可能包含任意正数个参数,这些参数由逗号分隔,每个参数表达式都是一个AssignmentExpression。这种非终结的递归定义是常见的。

5.1.5.3 可选符号

下标后缀“opt”,可出现在终结符或非终结符之后,表示一个可选符号。包含可选符号的替代项实际上指定了两个右侧,一个省略可选元素,一个包含它。这意味着:

VariableDeclaration : BindingIdentifier Initializeropt

是一个方便的缩写:

VariableDeclaration : BindingIdentifier BindingIdentifier Initializer

和:

ForStatement : for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement

是一个方便的缩写:

ForStatement : for ( LexicalDeclaration ; Expressionopt ) Statement for ( LexicalDeclaration Expression ; Expressionopt ) Statement

反过来又是一个缩写:

ForStatement : for ( LexicalDeclaration ; ) Statement for ( LexicalDeclaration ; Expression ) Statement for ( LexicalDeclaration Expression ; ) Statement for ( LexicalDeclaration Expression ; Expression ) Statement

因此,在这个例子中,非终结符ForStatement 实际上有四个备选右侧。

5.1.5.4 语法参数

一个产生式可能会被形式为“[parameters]”的下标注释参数化,它可能作为由产生式定义的非终结符号的后缀出现。“parameters”可以是单个名称或逗号分隔的名称列表。参数化的产生式是一组产生式的简写,这些产生式定义了所有参数名称的组合,这些名称由下划线前缀,并附加到参数化的非终结符号上。这意味着:

StatementList[Return] : ReturnStatement ExpressionStatement

是以下的缩写:

StatementList : ReturnStatement ExpressionStatement StatementList_Return : ReturnStatement ExpressionStatement

并且:

StatementList[Return, In] : ReturnStatement ExpressionStatement

是以下的缩写:

StatementList : ReturnStatement ExpressionStatement StatementList_Return : ReturnStatement ExpressionStatement StatementList_In : ReturnStatement ExpressionStatement StatementList_Return_In : ReturnStatement ExpressionStatement

多个参数会产生组合数量的产生式,但并不是所有的产生式都必须在完整的语法中被引用。

产生式右侧的非终结符号的引用也可以被参数化。例如:

StatementList : ReturnStatement ExpressionStatement[+In]

等同于说:

StatementList : ReturnStatement ExpressionStatement_In

以及:

StatementList : ReturnStatement ExpressionStatement[~In]

相当于:

StatementList : ReturnStatement ExpressionStatement

一个非终结符的引用可能同时具有参数列表和“opt”后缀。例如:

VariableDeclaration : BindingIdentifier Initializer[+In]opt

是以下的缩写:

VariableDeclaration : BindingIdentifier BindingIdentifier Initializer_In

在右侧非终结符引用中,用“?”前缀参数名称,使得该参数值依赖于当前产生式左侧符号引用中参数名称的出现。例如:

VariableDeclaration[In] : BindingIdentifier Initializer[?In]

是以下的缩写:

VariableDeclaration : BindingIdentifier Initializer VariableDeclaration_In : BindingIdentifier Initializer_In

如果右侧的备选方案以“[+parameter]”为前缀,那么这个备选方案只在引用产生式的非终结符号时使用了指定的参数才可用。如果右侧的备选方案以“[~parameter]”为前缀,那么这个备选方案只在引用产生式的非终结符号时使用指定的参数才可用。这意味着:

StatementList[Return] : [+Return] ReturnStatement ExpressionStatement

是以下的缩写:

StatementList : ExpressionStatement StatementList_Return : ReturnStatement ExpressionStatement

并且:

StatementList[Return] : [~Return] ReturnStatement ExpressionStatement

是以下的缩写:

StatementList : ReturnStatement ExpressionStatement StatementList_Return : ExpressionStatement

5.1.5.5 one of

当语法定义中的冒号后面跟着“one of”这几个词时,它们表示接下来的每一行上的终结符号都是一个替代定义。例如,ECMAScript的词法语法包含以下产生式:

NonZeroDigit :: one of 1 2 3 4 5 6 7 8 9

这只是一个方便的缩写,完整形式为:

NonZeroDigit :: 1 2 3 4 5 6 7 8 9

5.1.5.6 [empty]

如果产生式的右侧出现“[empty]”这一短语,它表示该产生式的右侧不包含任何终结符号或非终结符号。

5.1.5.7 前瞻限制

如果短语“[lookahead = seq]”出现在产生式的右侧,它表示只有当令牌序列seq是紧随其后的输入令牌序列的前缀时,才能使用该产生式。类似地,“[lookahead ∈ set]”,其中set是一个非空的有限令牌序列集合,表示只有当set中的某个元素是紧随其后的令牌序列的前缀时,才能使用该产生式。为了方便起见,该集合也可以写作非终结符,这种情况下它代表所有非终结符可以扩展到的令牌序列的集合。如果非终结符可以扩展到无限多个不同的令牌序列,则被认为是编辑错误。

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

例如,给定以下定义:

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

定义如下:

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

匹配字母n,后跟一个或多个十进制数字,第一个数字为偶数,或一个十进制数字,后面没有跟随另一个十进制数字。

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

5.1.5.8 [no LineTerminator here]

如果在句法文法的生成式右侧出现短语“[no LineTerminator here]”,则表示该生成式是受限生成式:如果在指示位置的输入流中出现 LineTerminator,则不允许使用该生成式。例如,生成式:

ThrowStatement : throw [no LineTerminator here] Expression ;

表示如果在脚本中 throw 标记和 Expression 之间出现 LineTerminator,则不允许使用该生成式。

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

5.1.5.9 but not

生成式的右侧可以使用短语“but not”并指示要排除的扩展来指定不允许某些扩展。例如,生成式:

Identifier :: IdentifierName but not ReservedWord

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

5.1.5.10 描述性短语

最后,在一些列出所有替代方案不切实际的情况下,使用无衬线字体的描述性短语来描述少数非终结符号:

SourceCharacter :: 任意 Unicode 代码点
<

5.2 算法约定

该规范经常使用编号列表来指定算法中的步骤。这些算法用于精确指定 ECMAScript 语言结构的所需语义。这些算法并不意味着必须使用任何特定的实现技术。实际上,可能有更有效的算法可用于实现给定的功能。

算法可以明确地用一个有序的、逗号分隔的别名序列参数化,这些别名在算法步骤中可用于引用在该位置传入的参数。可选参数用方括号([ , name ])表示,与算法步骤中的必需参数没有区别。参数列表的末尾可以出现一个剩余参数,以省略号(, ...name)表示。剩余参数捕获所有在必需参数和可选参数之后提供的参数,这些参数被编入一个 列表。如果没有这样的额外参数,那么这个 列表 将为空。

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

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

步骤或子步骤可以作为一个“if”谓词编写,条件化其子步骤。在这种情况下,只有当谓词为真时,子步骤才会被应用。如果步骤或子步骤以“else”一词开头,它是一个谓词,是与同一层级前一个“if”谓词步骤的否定。

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

以“Assert(断言):”开头的步骤断言其算法的不变条件。这种断言用来明确那些否则会是隐含的算法不变性。这样的断言不增加额外的语义要求,因此实现无需检查。它们仅用于澄清算法。

算法步骤可以使用“Let x be someValue”的形式声明任何值的命名别名。这些别名类似于引用,xsomeValue都指向相同的底层数据,对任何一个的修改都对双方可见。如果算法步骤想要避免这种类似引用的行为,应该明确地复制右侧值:“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语法之一的一个或多个产生式相关联。具有多个替代定义的产生式通常会为每个替代定义有一个独特的算法。当一个算法与一个语法产生式相关联时,它可以引用产生式替代的终结符和非终结符,就好像它们是算法的参数一样。在这种方式下使用时,非终结符引用在解析源文本时匹配的实际替代定义。由语法产生式匹配的源文本或由其衍生的解析节点是从参与匹配的第一个终结符开始到参与匹配的最后一个终结符结束的源文本部分。

当一个算法与一个产生式替代相关联时,该替代通常显示时不包括任何“[ ]”语法注释。这样的注释只应影响替代的语法识别,对替代的相关语义没有影响。

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

  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. Assertargument 是一个Completion Record
  2. 如果 argument 是一个abrupt completion,返回Completion(argument)。
  3. 否则,将 argument 设置为 argument.[[Value]]

算法步骤中提到或等同于:

  1. ReturnIfAbrupt(AbstractOperation())。

意味着:

  1. hygienicTemp 是 AbstractOperation()。
  2. AsserthygienicTemp 是一个Completion Record
  3. 如果 hygienicTemp 是一个abrupt completion,返回Completion(hygienicTemp)。
  4. 否则,将 hygienicTemp 设置为 hygienicTemp.[[Value]]

hygienicTemp 是短暂的,仅在涉及 ReturnIfAbrupt 的步骤中可见。

算法步骤中提到或等同于:

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

意味着:

  1. Assertargument 是一个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. Assertval 是一个正常完成
  3. val 设置为 val.[[Value]]

语法导向操作运行时语义中使用这种简写,通过在操作调用前放置!?

  1. 执行 ! SyntaxDirectedOperation of NonTerminal

5.2.3.5 隐式正常完成

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

如果通过任何其他方式从这样的抽象操作中返回完成记录,将是一个编辑错误。例如,在这些抽象操作中,

  1. 返回true

意味着与任何一种

  1. 返回NormalCompletion(true)。

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

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

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

  1. 返回 ? completion

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

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

5.2.4 静态语义

无上下文语法并不足以表达所有定义流式输入元素是否形成可评估的 ECMAScript ScriptModule 的规则。在某些情况下,需要使用 ECMAScript 算法约定或描述性要求来表达额外的规则。这些规则始终与语法的产生式相关联,并称为产生式的静态语义

静态语义规则具有名称,并通常使用算法定义。命名的静态语义规则与语法产生式相关联,具有多个备选定义的产生式通常对每个适用的命名静态语义规则有一个单独的算法。

静态语义规则的一种特殊类型是早期错误规则早期错误规则定义了特定语法产生式相关的早期错误条件(参见章节17)。大多数早期错误规则的评估在本规范的算法中未显式调用。符合要求的实现必须在首次评估ScriptModule之前,验证用于解析该ScriptModule的所有早期错误规则。如果违反了任何早期错误规则,则ScriptModule无效,无法评估。

5.2.5 数学运算

本规范参考以下数值类型:

  • 数学值:任意实数,作为默认的数值类型使用。
  • 扩展数学值数学值 加上 +∞ 和 -∞。
  • 数字:IEEE 754-2019 双精度浮点数值。参见 IEEE 754-2019
  • BigIntsECMAScript 语言值,表示与整数 整数 一一对应的任意整数。

在本规范的术语中,数值使用下标后缀来区分不同的数值类型。下标 𝔽 表示数字(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) 计算 x1xN 中的最小值。数学函数 max(x1, x2, ..., xN) 计算 x1xN 中的最大值。这些数学函数的定义域和值域为 扩展数学值

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

短语 "将 x 夹在 lowerupper 之间"(其中 x扩展数学值,而 lowerupper数学值,满足 lowerupper)的结果是:如果 x < lower,则产生 lower;如果 x > upper,则产生 upper;否则产生 x

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

floor(x) = x - (x 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 语言值粗体 显示。例如 nulltrue"hello"。这些与 ECMAScript 源文本Function.prototype.applylet n = 42; 区分开来。

5.2.7 身份

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

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

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

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

规范身份对于所有ECMAScript 语言值都与语言身份一致,除了由Symbol.for生成的Symbol值。没有规范身份和语言身份的ECMAScript语言值包括:undefinednull布尔值字符串数字,和大整数。具有规范身份和语言身份的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 类型表示具有两个值的逻辑实体,称为 truefalse

6.1.4 String 类型

String 类型是所有有序序列的集合,这些序列由零个或多个 16 位无符号整数值(“元素”)组成,最多可以有 253 - 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转义序列,字符串字面值也保证是标准化的。

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

短语“从 inclusiveStartexclusiveEnd子字符串”(其中 S 是一个字符串值或代码单元序列,而 inclusiveStartexclusiveEnd整数)表示由 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. lenstring 的长度。
  2. 如果 searchValue 是空字符串且 fromIndexlen,返回 fromIndex
  3. searchLensearchValue 的长度。
  4. 对于每个 整数 i 使得 fromIndexilen - searchLen,按升序执行:
    1. candidatestringii + searchLen子字符串
    2. 如果 candidatesearchValue,返回 i
  5. 返回 -1。
注 1

如果 searchValue 是空字符串且 fromIndexstring 的长度,该算法返回 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语言不提供这些类型之间的隐式转换。在调用需要另一种类型的函数时,程序员必须显式调用 NumberBigInt 函数进行类型转换。

ECMAScript 的早期和后续版本为某些运算符提供了隐式数值转换,这可能会损失精度或 截断。这些遗留的隐式转换保留了向后兼容性,但不适用于 BigInt,以减少程序员错误的可能性,并为未来版本中的泛型 值类型 留出选项。

6.1.6.1 数字类型(The Number Type)

数字类型(Number type)具有精确的 18,437,736,874,454,810,627 (即 264 - 253 + 3)个值, 表示双精度 64 位格式的 IEEE 754-2019 值,这些值按照 IEEE 二进制浮点算术标准规定。不同于 IEEE 标准的 9,007,199,254,740,990 (即 253 - 2)个“非数值(Not-a-Number)”值在 ECMAScript 中表示为单独的特殊值 NaN。 (注意,NaN 值由程序表达式 NaN 产生。)在一些实现中,外部代码可能能够检测到各种不同的非数值,但这种行为是 实现定义的; 对于 ECMAScript 代码来说,所有的 NaN 值都是无法区分的。

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

还有另外两个特殊值,分别称为 positive Infinitynegative Infinity。为了简洁起见,在解释目的上,这些值也被表示为符号 +∞𝔽-∞𝔽,分别。(注意,这两个无穷大的 Number 值由程序表达式 +Infinity(或简单地 Infinity)和 -Infinity 产生。)

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

注意,这里有一个 positive zero 和一个 negative zero。为了简洁起见,在解释目的上,这些值也被表示为符号 +0𝔽-0𝔽,分别。(注意,这两个不同的零 Number 值由程序表达式 +0(或简单地 0)和 -0 产生。)

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

18,428,729,675,200,069,632(即 264 - 254)个被规范化的值,具有以下形式:

s × m × 2e

其中,s 可以是 1 或 -1,m 是一个 整数,在区间从 252(包含)到 253(不包含)之间,而 e 是一个 整数,在区间从 -1074 到 971 的 包含区间内。

剩余的 9,007,199,254,740,990(即 253 - 2)个值是非规格化的,具有以下形式:

s × m × 2e

其中,s 可以是 1 或 -1,m 是一个 整数,在区间从 0(不包含)到 252(不包含)之间,而 e 是 -1074。

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

一个 有限数 的“奇数有效尾数”指的是,如果它是非零的,并且用来表示它的 整数 m(以上述两种形式之一)是奇数。否则,它具有“偶数有效尾数”。 在本规范中,“表示为数值的 Number 值 for x”这一短语表示选定以下方式的 Number 值。考虑所有的 Number 类型的 有限值,从中去除 -0𝔽,并额外添加两个不可表示的值,即 21024(即 +1 × 253 × 2971)和 -21024(即 -1 × 253 × 2971)。选择这个集合中与 x 最接近的成员。如果集合中有两个值同样接近,则选择有效尾数为偶数的那个;为此,额外的两个值 21024-21024 被认为具有偶数的有效尾数。最后,如果选择了 21024,则用 +∞𝔽 替换它;如果选择了 -21024,则用 -∞𝔽 替换它;如果选择了 +0𝔽,则仅当 x < 0 时,用 -0𝔽 替换它;否则使用选择的其他值而不变。结果就是 表示为数值的 Number 值 for x。(此过程与 IEEE 754-2019 roundTiesToEven 模式的行为完全对应。)

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

一些 ECMAScript 运算符只处理特定范围内的 整数,比如从 -231231 - 1闭区间或者从 0 到 216 - 1闭区间。这些运算符接受 Number 类型的任何值,但首先将每个这样的值转换为预期范围内的 整数 值。请参阅 7.1 中的数值转换操作描述。

6.1.6.1.1 Number::unaryMinus ( x )

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

  1. 如果 xNaN,则返回 NaN
  2. 返回取反后的结果 x;即具有相同大小但相反符号的 Number。

6.1.6.1.2 Number::bitwiseNOT ( x )

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

  1. oldValue 为 ! ToInt32(x)。
  2. 返回对 oldValue 应用按位补码操作的结果。该结果的 数学值 正好可表示为一个32位的二进制补码字符串。

6.1.6.1.3 Number::exponentiate ( base, exponent )

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

  1. 如果 exponentNaN,则返回 NaN
  2. 如果 exponent+0𝔽-0𝔽,则返回 1𝔽
  3. 如果 baseNaN,则返回 NaN
  4. 如果 base+∞𝔽,则
    1. 如果 exponent > +0𝔽,则返回 +∞𝔽。否则,返回 +0𝔽
  5. 如果 base-∞𝔽,则
    1. 如果 exponent > +0𝔽,那么
      1. 如果 exponent 是奇数的 integral Number,则返回 -∞𝔽。否则,返回 +∞𝔽
    2. 否则,
      1. 如果 exponent 是奇数的 integral Number,则返回 -0𝔽。否则,返回 +0𝔽
  6. 如果 base+0𝔽,则
    1. 如果 exponent > +0𝔽,则返回 +0𝔽。否则,返回 +∞𝔽
  7. 如果 base-0𝔽,则
    1. 如果 exponent > +0𝔽,那么
      1. 如果 exponent 是奇数的 integral Number,则返回 -0𝔽。否则,返回 +0𝔽
    2. 否则,
      1. 如果 exponent 是奇数的 integral Number,则返回 -∞𝔽。否则,返回 +∞𝔽
  8. Assert: base 是有限数,并且不是 +0𝔽-0𝔽
  9. 如果 exponent+∞𝔽,则
    1. 如果 abs((base)) > 1,则返回 +∞𝔽
    2. 如果 abs((base)) = 1,则返回 NaN
    3. 如果 abs((base)) < 1,则返回 +0𝔽
  10. 如果 exponent-∞𝔽,则
    1. 如果 abs((base)) > 1,则返回 +0𝔽
    2. 如果 abs((base)) = 1,则返回 NaN
    3. 如果 abs((base)) < 1,则返回 +∞𝔽
  11. Assert: exponentfinite,并且不是 +0𝔽-0𝔽
  12. 如果 base < -0𝔽,并且 exponent 不是一个 integral Number,则返回 NaN
  13. 返回一个表示将 (base) 的 (exponent) 次幂的结果的 implementation-approximated 数值。

base1𝔽-1𝔽,并且 exponent+∞𝔽-∞𝔽,或者当 base1𝔽exponentNaN𝔽 时,base ** exponent 的结果与 IEEE 754-2019 不同。ECMAScript 的第一版对于这个操作的结果规定为 NaN,而后来的 IEEE 754 标准修订版规定为 1𝔽。为了兼容性,保留了历史上 ECMAScript 的行为。

6.1.6.1.4 Number::multiply ( x, y )

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

  1. 如果 xNaN 或者 yNaN,则返回 NaN
  2. 如果 x+∞𝔽 或者 -∞𝔽,则
    1. 如果 y+0𝔽 或者 -0𝔽,则返回 NaN
    2. 如果 y > +0𝔽,则返回 x
    3. 返回 -x
  3. 如果 y+∞𝔽 或者 -∞𝔽,则
    1. 如果 x+0𝔽 或者 -0𝔽,则返回 NaN
    2. 如果 x > +0𝔽,则返回 y
    3. 返回 -y
  4. 如果 x-0𝔽,则
    1. 如果 y-0𝔽 或者 y < -0𝔽,则返回 +0𝔽
    2. 否则,返回 -0𝔽
  5. 如果 y-0𝔽,则
    1. 如果 x < -0𝔽,则返回 +0𝔽
    2. 否则,返回 -0𝔽
  6. 返回 𝔽((x) × (y))。

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

6.1.6.1.5 Number::divide ( x, y )

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

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

6.1.6.1.6 Number::remainder ( n, d )

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

  1. 如果 nNaN 或者 dNaN,返回 NaN
  2. 如果 n+∞𝔽 或者 -∞𝔽,返回 NaN
  3. 如果 d+∞𝔽 或者 -∞𝔽,返回 n
  4. 如果 d+0𝔽 或者 -0𝔽,返回 NaN
  5. 如果 n+0𝔽 或者 -0𝔽,返回 n
  6. Assert: ndfinite 的且非零。
  7. quotient(n) / (d)。
  8. qtruncate(quotient)。
  9. r(n) - ((d) × q)。
  10. 如果 r = 0 并且 n < -0𝔽,返回 -0𝔽
  11. 返回 𝔽(r)。
注1

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

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

6.1.6.1.7 Number::add ( x, y )

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

  1. 如果 xNaN 或者 yNaN,返回 NaN
  2. 如果 x+∞𝔽 并且 y-∞𝔽,返回 NaN
  3. 如果 x-∞𝔽 并且 y+∞𝔽,返回 NaN
  4. 如果 x+∞𝔽 或者 -∞𝔽,返回 x
  5. 如果 y+∞𝔽 或者 -∞𝔽,返回 y
  6. Assert: xy 都是 有限的
  7. 如果 x-0𝔽 并且 y-0𝔽,返回 -0𝔽
  8. 返回 𝔽((x) + (y))。

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

6.1.6.1.8 Number::subtract ( x, y )

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

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

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

6.1.6.1.9 Number::leftShift ( x, y )

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

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

6.1.6.1.10 Number::signedRightShift ( x, y )

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

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

6.1.6.1.11 Number::unsignedRightShift ( x, y )

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

  1. lnum 为 ! ToUint32(x)。
  2. rnum 为 ! ToUint32(y)。
  3. shiftCount(rnum) modulo 32。
  4. 返回将 lnum 右移 shiftCount 位并进行零填充的结果。空出的位将填充为零。结果的 数学值可准确表示为一个32位无符号位字符串。

6.1.6.1.12 Number::lessThan ( x, y )

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

  1. 如果 xNaN,则返回 undefined
  2. 如果 yNaN,则返回 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: xy 都是 finite
  11. 如果 (x) 小于 (y),则返回 true。否则,返回 false

6.1.6.1.13 Number::equal ( x, y )

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

  1. 如果 xNaN,则返回 false
  2. 如果 yNaN,则返回 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. 如果 xNaN 并且 yNaN,则返回 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. 如果 xNaN 并且 yNaN,则返回 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&,则
    1. result 为对 lbitsrbits 执行按位与操作的结果。
  6. 否则,如果 op^,则
    1. result 为对 lbitsrbits 执行按位异或(XOR)操作的结果。
  7. 否则,
    1. Assert:断言 op|
    2. result 为对 lbitsrbits 执行按位或操作的结果。
  8. 返回由 32 位二进制补码位字符串 result 表示的 Number value forinteger

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

以下观察可能对实现有指导作用,但不是本标准规范性要求的一部分:

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

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

  1. nks整数,使得 k ≥ 1,radixk - 1s < radixk𝔽(s × radixn - k) 是 x,并且 k 尽可能小。如果有多个可能的 s 值,选择使 s × radixn - k 最接近 (x) 的 s 值。如果有两个这样的可能值,选择偶数的那一个。注意,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. 如果 x0,返回 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. 如果 base0exponent0,返回 1
  3. 返回 baseexponent 次方。

6.1.6.2.4 BigInt::multiply ( x, y )

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

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

6.1.6.2.5 BigInt::divide ( x, y )

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

  1. 如果 y0,抛出一个 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. 如果 d0,抛出一个 RangeError 异常。
  2. 如果 n0,返回 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,则
    1. 返回 (floor((x) / 2-(y))).
  2. 返回 x × 2y.
这里的语义应该等同于按位左移,将 BigInt 视为无限长度的二进制补码数字字符串。

6.1.6.2.10 BigInt::signedRightShift ( x, y )

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

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

6.1.6.2.11 BigInt::unsignedRightShift ( x, y )

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

  1. 抛出一个 TypeError 异常。

6.1.6.2.12 BigInt::lessThan ( x, y )

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

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

6.1.6.2.13 BigInt::equal ( x, y )

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

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

6.1.6.2.14 BinaryAnd ( x, y )

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

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

6.1.6.2.15 BinaryOr ( x, y )

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

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

6.1.6.2.16 BinaryXor ( x, y )

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

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

6.1.6.2.17 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),
    1. xDigitx 取模 2。
    2. yDigity 取模 2。
    3. 如果 op&,那么
      1. result 设置为 result + 2shift × 按位与(xDigit, yDigit)。
    4. 否则如果 op|,那么
      1. result 设置为 result + 2shift × 按位或(xDigit, yDigit)。
    5. 否则
      1. 断言: op^
      2. result 设置为 result + 2shift × 按位异或(xDigit, yDigit)。
    6. shift 设置为 shift + 1。
    7. x 设置为 (x - xDigit) / 2。
    8. y 设置为 (y - yDigit) / 2。
  6. 如果 op&,那么
    1. tmp按位与(x 取模 2, y 取模 2)。
  7. 否则如果 op|,那么
    1. tmp按位或(x 取模 2, y 取模 2)。
  8. 否则
    1. 断言: op^
    2. tmp按位异或(x 取模 2, y 取模 2)。
  9. 如果 tmp ≠ 0,那么
    1. result 设置为 result - 2shift
    2. 注意:这扩展了符号位。
  10. 返回