Standard ECMA-262

9th Edition / March 2023

ECMAScript® 2018 Language Specification

关于与贡献

该规范是 ECMAScript 规范的中文翻译。当前版本对应 0d37f42 版本,我们的愿景是对该规范中文版本提供长期维护。目前翻译进度到第七章,有大量的 Pull Requests 需要校对,也希望有兴趣各路大神可参与该翻译的校对和审校工作。以下是一些参与贡献的渠道。

介绍

此标准定义了 ECMAScript 2018 语言,是 ECMAScript 语言规范的第九版。自从 1997 年第一版发布以来,ECMAScript 已经成为世界上应用最广泛的编程语言之一。他最为认知的是作为嵌入在 Web 浏览器中的语言,但也被广泛应用于服务器和嵌入式应用程序。

ECMAScript 基于几种始发技术,最著名的是 Netscape 的 JavaScript 以及 Microsoft 的 JScript。该语言由 Netscape 的 Brendan Eich 发明,并首次出现在该公司的 Navigator2.0 浏览器中。它已经出现在 Netscape 的所有后续浏览器以及 Microsoft 自 Internet Explorer3.0 开始的所有浏览器中。

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

该(第一版) Ecma 标准为了采用快速通道通过,被提交给 ISO/IEC JIC 1,于 1998 年 4 月被批准为国际标准 ISO/IEC16262。在 1998 年 Ecma 联合大会通过了第二版 ECMA-262,以保证完全符合 ISO/IEC 16262。第一版和第二版的变化是编辑层面的。

第三版标准引入了强大的正则表达式,更好的字符串处理,新的控制语句,try/catch 异常处理,更严格的错误定义,数字输出的格式化以及预期未来语言发展的微小变化。第三版 ECMAScript 标准于1999年12月被 Ecma 联合大会采纳,于 2002 年 6 月作为 ISO/IEC 16262:2002 发布。

在第三版发布后,ECMAScript 在万维网上被大量使用,它成为所有Web浏览器支持的编程语言。为了开发第四版 ECMAScript,做了大量有意义的工作,然而这项工作未能完成,也没能作为第四版 ECMAScript 发布,不过其中一些被纳入第六版开发(工作)中。

第五版 ECMAScript(以 ECMA-262 5th 版本发布)为那些已经被浏览器广泛实现的语言规范编纂了实质的解释,同时增加了对第三版发布以来出现的新功能的支持。 这些功能包括访问器属性对象的反向创建与检查对象属性特性的控制更多数组操作函数JSON对象编码格式的支持, 以及一种增强错误检查程序安全性严格模式。第五版于2009年12月Ecma联合大会采纳。

第五版为了采用快速通道通过,被提交给 ISO/IEC JIC 1,被批准为国际标准 ISO/IEC 16262:2011。第 5.1 版 ECMAScript 标准包含较少的更正,并与 ISO/IEC 16262:2011 保持一致。于2011年6月 Ecma 联合大会被采纳。

第六版于 2009 年开始作为重点开发,当时第五版正在准备出版。然而,这之前的重点实验以及语言增强设计工作可以追溯到 1999 年第三版发布。实际上,第六版的完成是十五年努力的结果。 这个版本中增加了包括对大型应用程序,库创建, 以及以 ECMAScript 作为其他语言的编译目标提供更好的支持。其中主要的增强功能包括模块化类声明词法块作用域迭代器以及生成器异步编程的promise解构模式,以及正确的尾部调用。 ECMAScript内置库扩展支持了额外的数据抽象,包括MapSet二进制值的数组, 同时也支持Unicode补充字符在字符串及正则表达式中使用。内置库也通过子类进行了扩展。第六版为正则渐进式语言以及库增强提供了基础。第六版于 2015 年 6 月被Ecma联合大会采纳。

ECMAScript2016使用 Ecma TC39 委员会新的年度发布策略以及公开开发流程的首个 ECMAScript 版本。从 ECMAScript2015 源文档作为基础构建一个纯文本的源文档,以支持完全在 GitHub 上进一步开发。在这个标准的发展的这一年,数百个pull requestsissues被提交,代表着成千上万的错误修复,编辑修复和其他改进。另外,许多软件工具被开发用来帮助这一工作,包括Ecmarkup,Ecmarkdown和Grammarkdown。ES2016还包括支持一个新的求幂运算符,以及为 Array.prototype 添加了一个名为include的新方法。

ECMAScript 2017 的规范引入了Async函数共享内存, 以及更小语言和库增强的原子错误修复,编辑更新。Async函数通过提供promise-returning函数语法来提高异步编程体验。共享内存和原子引入了一种新的内存模型,允许多个代理程序使用原子操作进行通信,以确保即便在并行 CPU 上程序也能有明确定义的执行顺序。此规范还包括 Object 新的静态方法:Object.valuesObject.entriesObject.getOwnPropertyDescriptors

本规范,第 9 版本通过引入异步迭代器协议和异步生成器支持异步迭代。该规范还包括四个新的正则表达式特性:dotAll 标志、命名的捕获组、Unicode 属性转义和后视断言。还包括REST参数和扩展运算符支持对象属性。也有许多小的更新,编辑和规范,贡献来自我们的社区。

许多个人和组织在 Ecma TC39 为当前版本以及以前的版本做出了非常重要的贡献。此外,有了一个充满活力的社区支持 TC39 为 ECMAScript 所做的努力。这个社区审查了许多草案,提交了大量的错误报告,执行实施实验,提供测试套件,全世界的 ECMAScript 的开发者都可以从中受益。然而遗憾的是,不能一一鸣谢为此做出贡献的每个人和组织。

Allen Wirfs-Brock
ECMA-262, 6th版本 项目编辑

Brian Terlson
ECMA-262, 7th版本 项目编辑

1 范围

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

2 一致性

一个符合ECMAScript标准的实现应该符合以下提议:

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

解释源文本的输入必须与最新版本的Unicode标准和ISO/IEC 10646标准保持一致。

提供的应用程序接口的程序,需要适应使用不同自然语言的国家的语言和文化习惯,且最新版本的ECMA-402的实现必须与本规范的接口兼容。

应该提供那些超出该规范描述的额外类型,值,对象,属性以及方法。尤其对于该文档有提到但没描述其属性的那些对象,应该提供那些属性以及属性对应的值。

应该支持一些没有在规范中提及的程序或者正则表达式语法。尤其应该实现在11.6.2.2列出的那些保留字的语法。

绝对不能实现在16.2列出的禁止的扩展。

3 引用标准

为了实现符合本规范的应用程序,下列引用文档是不可或缺的。对于标注了日期的文档,仅适用标注的那个版本。 对于未标注日期的文档,以文档的最新版为准(包括任何修订版)。

ISO/IEC 10646:2003: 信息技术 –通用多八位编码字符集(UCS)以及修订 1:2005, 修订 2:2006, 修订 3:2008, 和修订 4:2008, 以及其他修订,更正,后继标准

ECMA-402, ECMAScript 2015 国际化API规范.
http://www.ecma-international.org/publications/standards/Ecma-402.htm

ECMA-404, JSON 数据交换格式化.
http://www.ecma-international.org/publications/standards/Ecma-404.htm

4 概述

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

ECMAScript 是一门在宿主环境执行计算以及操作可计算对象的面向对象编程语言。这里定义的ECMAScript并不打算有自给自足的计算;事实上,该规范并没有规定外部数据的输入或者计算结果的输出。相反,我们期望 ECMAScript 程序的计算环境不仅提供本规范中描述的对象和能力,还包括特定的环境对象,本规范除了说明这些对象应该提供可被 ECMAScript 程序访问的某些属性,调用的某些方法外,关于它的其他描述和行为不在本规范涉及的范围。

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

ECMAScript 最初被设计为 Web 脚本语言,提供了一种让网页更加富有生机的机制,并能够进行部分基于Web B/S架构的服务器端计算。ECMAScript 现在被用于在多种宿主中提供核心脚本能力。因此该文档描述的是除特定宿主环境外的语言核心。

ECMAScript 用法已经远超出了简单脚本,现在被用于很多不同的环境和规模的全方位编程任务。随着 ECMAScript 使用范围的扩大使,其功能和能力也得到了扩展。ECMAScript 现在成为了一个功能齐全的通用编程语言。

ECMAScript 的一些能力类似于其他编程语言中,特别是 C, Java™, Self, 如以及下所述的 Scheme:

ISO/IEC 9899:1996, Programming Languages – C.

Gosling, James, Bill Joy and Guy Steele. The Java Language Specification. Addison Wesley Publishing Co., 1996.

Ungar, David, and Smith, Randall B. Self: The Power of Simplicity. OOPSLA '87 Conference Proceedings, pp. 227-241,Orlando, FL, October 1987.

IEEE Standard for the Scheme Programming Language. IEEE Std 1178-1990.

4.1 Web 脚本

web 浏览器提供用于客户端计算的 ECMAScript 宿主环境,包括如代表窗口,菜单,弹出窗口,对话框,文本域,锚点,框架,历史记录,cookies以及输入/输出的实例对象。此外,宿主环境还提供了脚本代码处理如焦点改变、页面和图片的加载、卸载、错误和中断,选择,表单提交和鼠标交互等等事件的能力。通过 HTML 中的脚本代码组合用户接口元素,固定及计算文本,图片来显示页面。脚本代码不需要一个主程序即可对用户交互进行响应。

WEB 服务器提供一个不同于客户端的如代表请求,客户端,文件等的对象,以及数据锁定和分享的机制。为基于 Web 的应用程序提供一个定制的用户界面,通过浏览器端脚本及服务端脚本的配合使用,可以在客户端和服务端之间进行分布式计算。

支持 ECMAScript 的 WEB 浏览器和服务器都将它们自身的宿主环境作为 ECMAScript 的补充,以使得 ECMAScript 的执行环境变得完整。

4.2 ECMAScript 概述

以下是 ECMAScript— 的非正式概述 —— 描述的只是该语言的一部分。这个概述不是标准的一部分。

ECMAScript 是基于对象的:基础语言以及主要能力都是通过对象提供,一个 ECMAScript 程序是一组可通信对象。在 ECMAScript 中,一个对象是零个或多个属性的的集合。每个属性都有确定其如何被使用的特性, 如当一个属性的 Writable 特性设置为 false 时,执行任何尝试对该属性分配不同值的的 ECMAScript 代码都将失败。属性是其他对象,原始值函数的容器。原始值是以下内置类型成员之一:Undefined, Null, Boolean, Number, String, and Symbol;一个对象是内置类型 Object 成员之一,一个函数是一个可调用对象。对象通过属性调用的函数叫做方法

ECMAScript 定义了一组内置对象,从而勾勒出 ECMAScript 实体的定义。这些内置对象包括全局对象;基本的语言运行时语义对象,包括 Object, Function, Boolean, Symbol,各种 Error 对象;代表和操作的数值对象,包括 Math, Number, Date;文本处理对象,StringRegExp;索引值集合的 Array 对象,以及九种值具有特定数字数据表示的 Typed Array 对象;泛型对象 Map, Set;支持结构化数据的 JSON, ArrayBuffer, SharedArrayBuffer,DataView 等对象;支持控制抽象的 generator 函数,Promise 对象;以及反射对象 ProxyReflect

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

大型 ECMAScript 程序通过模块被支持,其允许程序可以被分化为多个语句和定义序列。每个模块明确地标识它所使用的其他模块提供的声明,哪些声明可供其他模块使用。

ECMAScript 语法有意地类似于 Java 语法。ECMAScript 语法是松散的,使其能够成为易于使用的脚本语言。例如,一个变量不需要声明其具体类型,也不需要与声明相关联属性类型,在调用定义的函数之前也不需要以文本方式显示的声明。

4.2.1 Objects

尽管 ECMAScript 包含了定义类的语法,但是 ECMAScript 对象从根本上来说并不是像 C++,Smalltalk,Java 那样基于类的。相反,对象可以通过各种方式创建,包括字面符号,或通过构造器创建对象然后运行代码初始化其全部或部分属性值,为这些属性分配初始值。每个构造器是一个拥有名为 "prototype" 的属性的函数,此属性用于实现基于原型的继承共享属性构造器通过 new 表达式创建对象:例如,new Date(2009, 11) 创建一个新 Date 对象。不使用new调用一个构造器的结果由构造器本身决定。例如,Date()产生一个表示当前日期时间的字符串,而不是一个对象。

每个由构造器创建的对象,都有一个隐式引用(叫做对象的原型)链接到构造器"prototype" 属性值。再者,一个原型可能有一个非空隐式引用链接到它的原型,以此类推,这叫做原型链。当向对象的一个属性提出引用时,引用会指向原型链中包含此属性名的第一个对象的属性。换句话说,首先检查直接提及的对象的同名属性,如果对象包含同名的属性,引用即指向此属性,如果该对象不包含同名的属性,则下一步检查对象的原型;以此类推。

Figure 1: Object/Prototype Relationships
An image of lots of boxes and arrows.

一般情况下基于类的面向对象语言的实例拥有状态,类拥有方法,并且只能继承结构和行为。在 ECMAScript 中,对象拥有状态和方法,并且结构,行为,状态全都可继承。

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

CF 是一个构造器(也是一个对象)。五个对象已用 new 表达式创建: cf1, cf2, cf3, cf4, cf5。每个对象都有名为 q1q2 的属性。虚线表示隐式原型关系;例如:cf3 的原型是 CFp构造器 CF 自己有名为 P1P2 的两个属性, 这对 CFp,cf1, cf2, cf3, cf4, cf5 是不可见的。CFp 的名为 CFP1 的属性共享给 cf1, cf2,cf3, cf4, 以及 cf5 ( 没有CF), 以及在 CFp 的隐式原型链中找不到任何名为 q1, q2,或 CFP1 的属性。请注意,CFCFp 之间没有隐式原型链接。

不同于基于类的对象语言,属性可以通过赋值的方式动态添加给对象。也就是说,构造器并不是非要对构造的对象的全部或任何属性命名或赋值。上图中,可以给 CFp 添加新属性值的方式为 cf1, cf2, cf3, cf4,and cf5 添加一个新的共享属性。

尽管 ECMAScript 对象本质上不是基于类,但是基于构造函数,原型对象和方法通用模式来实现类似于类的抽象是很方便的。ECMAScript 内置对象本身即遵循这样的类模式。从 ECMAScript 2015 开始,ECMAScript 语言包含了类定义语法,允许程序员像内置对象那样简洁的定义对象。

4.2.2 ECMAScript 严格变体

ECMAScript 语言认识到有的开发者可能希望限制使用语言中的新特性。他们这样做可能是为了安全考虑,避免他们认为是容易出错的功能,获得增强的错误检查,或其他原因。因此,ECMAScript 中定义了语言的严格变体。语言的严格变体,排除了 ECMAScript 语言的某些特定的语法和语义特征,还修改了某些功能的详细语义。严格变体还指定了必须抛出错误异常报告的额外错误条件,即使在非严格的语言形式下这些条件不属于错误。

ECMAScript 的严格变体通常被称为语言的严格模式。严格模式选择和使用明确地适用于独特 ECMAScript 代码单元级别的,ECMAScript 严格模式语法和语义。由于语法代码单元级别的严格模式被选择,严格模式仅在这个代码单元内施加有局部效果的限制。严格模式不限制或修改任何层面的 ECMAScript 语义,必须一致地操作跨多个代码单元。一个 ECMAScript 程序可同时包含严格模式和非严格模式的代码单元。在这种情况下,严格的模式只适用于严格模式代码单元内实际执行的代码。

要符合这一规范,ECMAScript 的实现必须同时实现未限制的 ECMAScript 语言和按照这个规范定义的 ECMAScript 的严格模式变体。此外,实现还必须支持未限制的和严格模式代码单元的在同一个程序中混用。

4.3 术语与定义

本文档将使用下列术语和定义。

4.3.1 类型

在本规范6中定义的数据值集合。

4.3.2 原始值

指在6中定义的 Undefined, Null, Boolean, Number, Symbol, String 类型之一

Note

一个原始值直接代表语言实现的最低层次的数据

4.3.3 对象

Object 类型的成员

Note

对象是属性的集合,并且具有单个原型对象。原型可能是空值

4.3.4 构造函数

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

Note

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

4.3.5 原型

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

Note

构造器创建一个对象,为了解决对象的属性引用,该对象会隐式引用构造器prototype 属性。通过程序表达式 _constructor_.prototype 可以引用到构造器prototype 属性,添加到对象原型里的属性是被共享的,通过继承,所有对象都共享此原型。另外,可使用Object.create内置函数,通过显式的指定原型来创建一个新对象。

4.3.6 普通对象

默认行为拥有如那些所有对象都必须支持的内部方法的对象

4.3.7 异常对象

默认行为缺少一个或多个必要内部方法的对象

Note

任何对象不是普通对象就是异常对象。

4.3.8 标准对象

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

4.3.9 内置对象

ECMAScript 实现指定和提供的对象

Note

标准的内置对象由本规范定义,ECMAScript 实现可以指定和定义其他的一个内置构造器是个内置对象,也是个构造器

4.3.10 未定义的值

一个在变量没有被赋值时就被使用的原始值

4.3.11 Undefined 类型

值只有 undefined 值的类型

4.3.12 空值

表示故意缺省任何对象值的原始值

4.3.13 Null 类型

值只有 null 值的类型

4.3.14 Boolean 值

Boolean 类型的成员

Note

只有两个值, truefalse

4.3.15 Boolean 类型

由原始值 truefalse 组成的类型

4.3.16 Boolean 对象

标准内置构造函数 Boolean 的实例,Object 类型成员之一

Note

通过使用 new 表达式,以一个 Boolean 值作为参数调用 Boolean 构造器来创建 Boolean 对象。由此产生的对象包含一个值为此 Boolean 值的内部属性。一个 Boolean 对象可以强制转换为 Boolean 值。

4.3.17 String 值

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

Note

一个 String 值是 String 类型的成员。通常序列中的每个整数值代表 UTF-16 文本的单个 16 位单元。然而,对于其值,ECMAScript 只要求必须是 16 位无符号整数,除此之外没有任何限制或要求。

4.3.18 String 类型

所有可能的 String 值的集合

4.3.19 String 对象

标准内置构造器 String 实例,Object 类型成员之一

Note

通过使用 new 表达式,以一个 String 值为参数调用 String 构造器来创建 String 对象。由此产生的对象包含一个值为此 String 值的内部属性。将 String 构造器作为一个函数来调用,可将一个 String 对象强制转换为一个 String 值(21.1.1.1)。

4.3.20 Number 值

IEEE 754-2008 格式的 64 位双精度二进制的原始值

Note

一个数字值是数字类型的成员,直接代表一个数字。

4.3.21 Number 类型

所有可能的 Number 值的集合,包括特殊 “Not-a-Number” (NaN) 值, 正无穷, 负无穷

4.3.22 Number 对象

标准内置构造器 Number 的一个实例,Object 类型成员之一

Note

通过使用 new 表达式,以一个数字值为参数调用 Number 构造器来创建 Number 对象。由此产生的对象包含一个值为此 Number 值的内部属性。将 Number 构造器作为一个函数来调用,可将一个 Number 对象强制转换为一个数字值(20.1.1.1)。

4.3.23 无穷

正无穷数值

4.3.24 NaN

值 IEEE 754-2008 “Not-a-Number” 的数值

4.3.25 Symbol 值

表示一个唯一的,非字符串的属性键对象的原始值

4.3.26 Symbol 类型

所有可能的 Symbol 值集合

4.3.27 Symbol 对象

标准内置构造器 Symbol 的一个实例,Object 类型成员之一

4.3.28 函数

可作为子程序调用的 Object 类型成员之一

Note

函数除了其属性,还包含可执行代码、状态,用来确定被调用时的行为。函数的代码不限于 ECMAScript。

4.3.29 内置函数

作为函数的内置对象

Note

如 parseInt 和 Math.exp 就是内置函数。一个实现可以提供本规范没有描述的依赖于实现的内置函数。

4.3.30 属性

将一个键(一个 String 值或 Symbor 值)和值相关联的对象的一部分

Note

属性可能根据属性值的不同表现为直接的数据值(原始值,对象,或一个函数对象)或间接的一对访问器函数。

4.3.31 方法

作为属性值的函数

Note

当一个函数被作为一个对象的方法调用,此对象将作为 this 值传���给函数。

4.3.32 内置方法

作为内置函数的方法

Note

标准内置方法由本规范定义,ECMAScript 实现可指定,提供其他额外的内置方法。

4.3.33 特性

定义一个属性的一些特性的内部值

4.3.34 自身属性

对象直接拥有的属性

4.3.35 继承属性

不是对象的自身属性,但是是对象原型的属性(原型的自身属性或继承属性)

4.4 本规范的结构

本规范的剩余部分章节组织如下:

第 5 章定义了在本规范中使用的一些符号或者语法的约定。

第 6-9 章定义了 ECMAScript 程序操作包含的执行环境。

第 10-16 章定义了实际的 ECMAScript 语言,包括它的语法编码以及语言特性的执行语义。

第 17-26 章定义了 ECMAScript 标准库。它们包括所有当 ECMAScript 程序执行时可用的标准对象的定义。

第 27 章描述了访问备用数组缓冲区内存和原子对象的内存一致性模型。

5 符号约定

5.1 语法与词法

5.1.1 上下文无关文法

上下文无关文法由多个产生式组成。每个产生式左侧有一个称为非终结符的抽象符号的左值,右侧有一个或多个非终结符和终结符号组成的序列的右值。任何文法,它的终结符都来自指定的字母集。

一个产生式链是一个只含有一个非终结符以及 0 个或多个终结符作为其右值的产生式。

句子中单一可区分的非终结符——目标符,给定一个语言上下文无关文法。换句话说,重复用产生式右值替换序列中任何左值为非终结符所组成的终结符序列集合(可能是无限个)。

5.1.2 词法与正则文法

ECMAScript 词法文法11 给出。词法文法拥有符合 10.1 定义的 SourceCharacter 规则的终结符 Unicode 码点。它定义了一套产生式,从目标符 InputElementDiv, InputElementTemplateTail,或 InputElementRegExp, InputElementRegExpOrTemplateTail 起始,描述如何将这样的字符序列翻译成一个输入元素序列。

空白和注释之外的输入元素构成 ECMAScript 语法文法的终结符,它们被称为 ECMAScript tokens。这些 tokens 是,ECMAScript 语言的保留字,标识符,字面量,标点符号。此外,行结束符虽然不被视为 tokens,但会成为输入元素流的一部分,用于引导处理自动插入分号(11.9)。单个空白和单行注释会的丢弃,不会出现在语法文法的输入元素的流中。如果一个 MultiLineComment(即形式为 /**/ 的注释,不管是否跨越多行)不包含行结束符也会直接地丢弃,但如果一个 MultiLineComment 包含一个或多个结束符,那么,注释会被替换为一个行结束符,成为语法文法输入元素流的一部分。

21.2.1 给出了 ECMAScript 的正则文法。此文法的终结符字符也由 SourceCharacter 定义。它定义了一套产生式,从目标符 Pattern 起始,描述了如何将这样的字符序列翻译成一个正则表达式模式。

两个冒号 "::" 作为分隔符分割词法和正则的文法产生式。词法和正则的文法共享某些产生式。

5.1.3 数字字符串文法

用于转换字符串为数字值的一种文法。此文法与数字字面量词法文法的一部分类似,并且有终结符 SourceCharacter。此文法出现在 7.1.3.1

三个冒号 ":::" 作为分隔符分割数字字符串文法的产生式。

5.1.4 语法文法

第 11,12,13,14,15 章给出了 ECMAScript 的语法文法。词法文法定义的 ECMAScript tokens 是此文法的终结符(5.1.2)。它定义了一系列的产生式,从两个可选的目标符Script 以及 Module 开始,描述了形成 ECMAScript 程序语法上正常的独立的组件的 token 是怎样的序列。

当一个码点流解析成一个 ECMAScript 的 Script 或者 Module 时,它首先被词法文法程序转换成一个输入元素流;然后使用一个单一语法文法程序解析这个输入元素流。存在语法错误 —— 输入元素流中的 token 不能被解析成一个单一的目标非终结符(Script 或者 Module)—— 的输入流,将不会留下任何 token。

当一个解析成功的时候,它会构造一颗解析树,一颗根树结构是它的每个节点都是一个 Parse Node。每个 Parse Node 都是文法中的一个符号的一个实例。它代表了从这样的符号中派生出来的源代码文本的一个跨度。解析树的根节点代表着整个的源代码文本,是解析的目标符的一个实例。当一个 Parse Node 是一个非终结符的实例的时候,它也是某些左值为非终结符的产生式的一个实例。此外,它有 0 个或多个孩子,产生式右值中的每个符号:每个孩子的 Parse Node 都是相应符号的一个实例。

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

Note 1

多次解析同一字符串会得到不同的 Parse Nodes,例如:

eval(str); eval(str);
Note 2
Parse Nodes 是规范的人为定义,并且不需要使用类似的数据结构来实现。

只用一个冒号 “:” 作为分隔符分割语法词法的产生式。

语法文法在条款 12,13,14,15 中提出。但是对于哪些 token 序列是正确被 ECMAScript Script 或者 Module 接受的解释得并不完整。一些额外的 token 序列也能被接受,换句话说,那些序列将会被文法描述,只要分号被加入到序列中的某些地方(比如在行终结符之前)。此外,某些通过文法描述的 token 序列不会被接受,如果一个行终结符出现在某些 “awkward” 的地方。

在某些情况下,为了避免歧义,语法文法使用广义的产生式,允许 token 序列形成一个不合法的 ECMAScript Script 或者 Module。例如,此技术被用作对象字面量和对象解构模式中。在这种情况下,提供了更加限制性的补充文法,其进一步限制可接受的 token 序列。通常,如果 "P is not covering an N",则一个早期错误规则将会定义一个错误条件,其中 P 是 Parse Node(普通产生式的一个实例),N 是补充文法的非终结符。这里,最初与 P 匹配的 token 序列被再次用 N 作为目标符号解析。(如果 N 使用语法参数,则将它们设置为当 P 最初解析时使用的相同值)。如果 token 序列不能被解析为 N 的一个单一实例,则会产生错误,将不会留下任何 token。随后,算法访问 "the N that is covered by P" 的短语的解析结果。这将始终是一个解析节点(N 的一个实例,对于一个给定的 P 是唯一的),因此任何解析失败都将被一个早期错误规则检测到。

5.1.5 文法标记法

不管是在文法的产生式,还是在本规范中,词法文法,正则文法以及数字字符串文法的终结符都用等宽字体展示。这些将以的脚本形式出现。所有通过这种方式指定的终结符码点都被当作合适的基本拉丁语 Unicode 码点理解,而不是来自其他任何类似 Unicode 范围的码点。

非终结符以斜体显示。非终结符(也叫产生式)的定义由非终结符名称和其后定义的一个或多个冒号给出。(冒号的数量表示产生式所属的文法。)非终结符的一个或多个替代右值紧跟在下一行。例如,语法定义:

WhileStatement:while(Expression)Statement

表示这个非终结符 WhileStatement 代表 while token,其后跟左括号 token,其后跟 Expression,其后跟右括号 token,其后跟 Statement。这里出现的 ExpressionStatement 本身是非终结符。另一个例子,语法定义:

ArgumentList:AssignmentExpression ArgumentList,AssignmentExpression

表示这个 ArgumentList 可以代表一个 AssignmentExpression,或 ArgumentList,其后跟一个逗号,其后跟一个 AssignmentExpression。这个 ArgumentList 的定义是递归的,也就是说,它定义它自身。其结果是,一个 ArgumentList 可能包含用逗号隔开的任意正数个参数,每个参数表达式是一个 AssignmentExpression。这样,非终结符共用了递归的定义。

终结符或非终结符可能会出现后缀下标 “opt”,表示它是可选符号。包含可选符号实际指定了包含两个右值,一个是省略可选元素的,另一个是包含可选元素的。这意味着:

VariableDeclaration:BindingIdentifierInitializeropt

是以下的一种简便的缩写:

VariableDeclaration:BindingIdentifier BindingIdentifierInitializer

以及:

IterationStatement:for(LexicalDeclarationExpressionopt;Expressionopt)Statement

是以下的一种简便的缩写:

IterationStatement:for(LexicalDeclaration;Expressionopt)Statement for(LexicalDeclarationExpression;Expressionopt)Statement

也是下面的一种缩写:

IterationStatement:for(LexicalDeclaration;)Statement for(LexicalDeclaration;Expression)Statement for(LexicalDeclarationExpression;)Statement for(LexicalDeclarationExpression;Expression)Statement

所以在这个例子中,非终结符 IterationStatement 实际上有四个可供选择的右值。

产生式可以通过形如 “[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:BindingIdentifierInitializer[+In]opt

是下面的缩写:

VariableDeclaration:BindingIdentifier BindingIdentifierInitializer_In

在右侧非终结符引用参数名称前置以 “?”,使该参数值取决于当前产生式的左侧符号引用的参数名称是否出现。例如:

VariableDeclaration[In]:BindingIdentifierInitializer[?In]

是下面的缩写:

VariableDeclaration:BindingIdentifierInitializer VariableDeclaration_In:BindingIdentifierInitializer_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

在文法定义中当单词 “one of” 跟随一个或多个分号后的时候,表示随后的一行或多行的终结符是一个可选的定义。例如,ECMAScript的词法文法包含下列的产生式:

NonZeroDigit::one of123456789

它仅仅是下面的缩写:

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

如果 “[empty]” 出现在一个产生式的右值,它暗示着这个产生式的右值不包含终结符或者非终结符。

如果 “[lookahead ∉ set]” 出现在一个产生式的右值,它暗示着如果随后立即的输入的token序列是给出的集合(set)的成员,那么这个产生式也许不会被使用。这个集合可以用一个逗号分割的由一到两个被花括号包裹的元素终结序列的列表表示。为了方便,这个集合也可以用非终结符表示,在这种情况下,它代表所有能由非终结符展开得到的终结符的集合。如果这个集合包含一个单独的终结符,那么短语 “[lookahead ≠ terminal]” 也许会被使用。

例如,给出定义:

DecimalDigit::one of0123456789 DecimalDigits::DecimalDigit DecimalDigitsDecimalDigit

则定义:

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

能匹配字母 n 后跟随由偶数起始的一个或多个十进制数字,或一个十进制数字后面跟随一个非十进制数字。

类似的,如果产生式的右值出现 “[lookahead ∈ set]”,则表示产生式只有在随后立即的输入的token序列是给出的集合(set)的成员才能使用。如果集合只包含一个单一的终结符,则可以使用 “[lookahead == terminal]”。

如果产生式的右侧出现 “[no LineTerminator here]”,那么它表示此产生式是个受限的产生式:如果 LineTerminator 在输入流的指定位置出现,那么此产生式将不会被适用。例如,产生式:

ThrowStatement:throw[no LineTerminator here]Expression;

如果一个 LineTerminator 出现在脚本的 throw token 和 Expression 之间的时候,暗示着这个产生式也许不会被使用。

除非通过一个受限的产生式禁止一个 LineTerminator 的出现,否则任意数量 LineTerminator 的出现也许会发生在输入元素流中任意两个连续的 token 之间,并且不影响脚本的语义可接受性。

当一个词法文法或者数字字符串文法的产生式中可选部分出现多码点的 token 时,意味着码点序列将会组成一个 token。

一个产生式的右值也许会通过 “but not” 指定某些不被允许的扩展,然后暗示这个扩展将是被排除在外的。例如,产生式:

Identifier::IdentifierNamebut not ReservedWord

意味着非终结符 Identifier 也许会被任意的码点序列替换,这些码点能够替换提供的 IdentifierName,但是相同序列的码点不能替换 ReservedWord

最后,一些非终结符通过 sans-serif 字体书写的描述性的短语来描述, 在这样的案例中,列出所有的可选部分是不切实际的。

SourceCharacter::any Unicode code point

5.2 算法约定

此规范通常使用带编号的列表来指定算法的步骤。这些算法是用来精确地指定 ECMAScript 语言结构所需的语义。该算法无意暗示任何具体实现使用的技术。在实践中,也许可用更有效的算法实现一个给定功能。

算法可能被显式参数化,在这种情况下,参数名和用法必须作为算法定义的一部分提供。

算法步骤可以细分为多个连续的子步骤。子步骤需要用缩进表示,可以进一步被划分成缩进的子步骤。大纲编号约定用作标识子步骤,第一级子步骤使用小写字母字符标记,第二级小步骤用小写罗马数字标记。如果步骤超过三级,那么这些规则从第四级开始从数字重复进行标记。例如:

  1. Top-level step
    1. Substep.
    2. Substep.
      1. Subsubstep.
        1. Subsubsubstep
          1. Subsubsubsubstep
            1. Subsubsubsubsubstep

一个步骤或者子步骤也许会使用 “if” 去断言它的子步骤的条件。在这样的案例中,这些子步骤只能适用于 “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. Let status be the result of performing SyntaxDirectedOperation of SomeNonTerminal.
  2. Let someParseNode be the parse of some source text.
  3. Perform SyntaxDirectedOperation of someParseNode.
  4. Perform SyntaxDirectedOperation of someParseNode passing "value" as the argument.

除非另有明确说明,否则,所有相关联的产生式对于每个也许会被应用到这个产生式左值的非终结符的操作都有一个隐式的定义。如果存在的话,这个隐式的定义简单地再次对同样的参数运用这个相同的定义,对于这些相关联的产生式唯一的右值非终结符,随后返回处理结果。例如,假设一些算法有如下形式的步骤: “Return the result of evaluating Block”,并且这里有一个产生式:

Block:{StatementList}

但是解析操作并没有关联这个产生式的算法。那么在这样的案例中,解析操作隐式地包含了下面形式的关联:

运行时语义: 解析

Block:{StatementList}
  1. Return the result of evaluating StatementList.

5.2.3 运行时语义

必须在运行时被调用的指定语义的算法就叫运行时语义。 运行时语义通过抽象操作或者指定语法操作来定义。这样的算法必须返回一个完成记录。

5.2.3.1 隐式完成值

本规范的算法常常隐式地返回一个 [[Type]] 值为 normalCompletion Records。除非一个返回一个值的算法语句在上下文明显指定返回一个不是 Completion Record 的值。例如:

  1. Return "Infinity".

与下面的是同一个含义:

  1. Return NormalCompletion("Infinity").

然而,如果一个 “return” 语句的值表达式是一个 Completion Record 构造的字面量,那么 Completion Record 的结果将被返回。如果这个值表达式是一个对抽象操作的调用,那么 “return” 语句简单地返回这个抽象操作产生的 Completion Record

抽象操作 Completion(completionRecord) 被用作强调之前计算的 Completion Record 被返回。Completion 这个抽象操作接收一个参数,即 completionRecord,然后执行下面的步骤:

  1. Assert: completionRecord is a Completion Record.
  2. Return completionRecord as the Completion Record of this abstract operation.

一个在算法步骤中没有值的 “return” 语句与下面的是同样的意思:

  1. Return NormalCompletion(undefined).

对于任意的在一个上下文中没有显示地需要一个完整的 Completion Record 值的引用,等价于一个显式地对 Completion Record 的 [[Value]] 字段的引用,除非 Completion Record 是一个中断完成

5.2.3.2 抛出一个异常

描述抛出一个异常的算法步骤,例如:

  1. Throw a TypeError exception.

与下面的是同一个含义:

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

5.2.3.3 ReturnIfAbrupt

算法步骤说明或者等同于:

  1. ReturnIfAbrupt(argument).

意思就是:

  1. If argument is an abrupt completion, return argument.
  2. Else if argument is a Completion Record, let argument be argument.[[Value]].

算法步骤说明或者等同于:

  1. ReturnIfAbrupt(AbstractOperation()).

与下面的是同一个含义:

  1. Let hygienicTemp be AbstractOperation().
  2. If hygienicTemp is an abrupt completion, return hygienicTemp.
  3. Else if hygienicTemp is a Completion Record, let hygienicTemp be hygienicTemp.[[Value]].

这里的 hygienicTemp 是临时的,并且只在 ReturnIfAbrupt 有关的步骤中中可见。

算法步骤说明或者等同于:

  1. Let result be AbstractOperation(ReturnIfAbrupt(argument)).

与下面的是同一个含义:

  1. If argument is an abrupt completion, return argument.
  2. If argument is a Completion Record, let argument be argument.[[Value]].
  3. Let result be AbstractOperation(argument).

5.2.3.4 ReturnIfAbrupt 缩写

抽象操作和以 ? 为前缀的指定语法操作的调用暗示着 ReturnIfAbrupt 需要被应用到结果的 Completion Record 中。 例如,步骤:

  1. ? OperationName().

等价于下面的步骤:

  1. ReturnIfAbrupt(OperationName()).

相似的,对于程序方法的风格,步骤:

  1. ? someValue.OperationName().

等价于:

  1. ReturnIfAbrupt(someValue.OperationName()).

相似的,前缀 ! 被用作暗示下列的对于抽象或者指定语法操作的调用将不会返回一个打断的完成值, 并且作为结果的 Completion Record 的 [[Value]] 字段应该被用作替换操作的返回值。 例如,步骤:

  1. Let val be ! OperationName().

等价于下面的步骤:

  1. Let val be OperationName().
  2. Assert: val is never an abrupt completion.
  3. If val is a Completion Record, set val to val.[[Value]].

对于运行时语义的指定语法的操作通过在调用操作前替换 ! 或者 ? 来利用这个缩写。

  1. Perform ! SyntaxDirectedOperation of NonTerminal.

5.2.4 静态语义

上下文无关文法不能足够好的去表达所有定义的规则,不管是一个输入元素的流形成的一个合法的将被解析的 ECMAScript Script 还是 Module。在一些情况中,需要额外的规则通过使用 ECMAScript 算法约定或者散文要求来展示。这样的规则总是与一个文法的产生式相关联,被称作产生式的静态语义

静态语义规则拥有名称,并且通常用一个算法来定义。具有名称的静态语义规则与文法产生式相关联,对于每个可采用的具有名称的静态语义规则, 一个包含多个可选部分定义的产生式通常会对每个可选部分定义一个独有的算法。

除非在本规范中其它指定的文法产生式可选部分隐式地包含一个叫做 Contains 的接收一个值为包含相关产生式的文法的终结符或者非终结符的 symbol 参数静态语义规则的定义。 默认的包含定义为:

  1. For each child node child of this Parse Node, do
    1. If child is an instance of symbol, return true.
    2. If child is an instance of a nonterminal, then
      1. Let contained be the result of child Contains symbol.
      2. If contained is true, return true.
  2. Return false.

上面的定义是显式地重写了规范的产生式。

一个特殊的静态语义规则是早期(提前)错误规则。早期错误规则定了早期错误条件(见 16),它们与具体的文法产生式相关联。大多数早期错误规则的解析不是在本规范的算法中显式地被调用。一个符合规范的实现必须在第一次解析 Script 或者 Module 之前,验证所有被用作解析 Script 或者 Module 的产生式的早期错误规则。如果违反了任意的早期错误规则,那么 Script 或者 Module 就是不合法的,并且不能被解析执行。

5.2.5 数学操作

除非其它地方特别注明不包括无限并且不包括负 0(为了与正 0 区分),数学操作,例如加,减,否定(逻辑非),乘,除以及随后在条款中定义的数学函数应总是被当作是对于数学中所有真实数字计算出来的准确的结果。本规范算法中的浮点运算包含显式地的步骤,它们对于处理无穷,有符号的0,以及舍入是必要的。如果一个数学操作或者函数被应用在一个浮点数上,那么它必须被当作应用到用浮点数表示的具体的数学值;这样的浮点数必须是有限的,并且如果它是 +0 或者 -0 的话,那么相应的数学值就是简简单单的 0。

数学函数 abs(x) 用来计算 x 的绝对值,如果 x 是负数,那么结果就是 -x,否则结果就是 x 本身。

数学函数 min(x1, x2, ..., xN) 计算从 x1xN 的最小值。 数学函数 max(x1, x2, ..., xN) 计算从 x1xN 的最大值。 这些数学函数的域以及范围包括 +∞-∞

符号 “x modulo y” ( y 必须是有限的且是非 0 的)计算出一个值 k, 它的符号与 y 一致(或者是 0),这样的 k 满足 abs(k) < abs(y),以及能找到某个整数y,使得 x-k = q * y

��学函数 floor(x) 产生一个不大于 x 的最大整数(最接近正无穷)。

Note

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

6 ECMAScript 数据类型和值

本规范中算法控制每个具有相关类型的值。可能的值类型直接定义在本章节中。这些类型进一步分为 ECMAScript 语言类型与规范类型。

在本规范中,“Type(x)”表示法是“the type of x”的简写, 其中“type”指的是在本章节中定义的 ECMAScript 语言类型与规范类型。当一个值使用术语“empty”命名值时,它相当于说“没有任何类型的值”。

6.1 ECMAScript 语言类型

一个 ECMAScript 语言类型对应那些 ECMAScript 程序员在 ECMAScript 语言中直接使用的值。 ECMAScript 语言类型有 Undefined, Null, Boolean, String,Symbol, Number, 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 个元素。字符串类型通常用于表示正在运行的 ECMAScript 程序中的文本数据,在这种情况下,String中的每个元素都被视为一个 UTF-16 码元。 每个元素被认为占据该序列内的一个位置。 这些位置用非负整数索引。 第一个元素(如果有)在索引 0 处,下一个元素(如果有的话)在索引 1 处,以此类推。 String 的长度是序列中的元素个数(例如,十六位值)。空字符串的长度为零,因此不包含元素。

ECMAScript 操作符不应用不同的语义解释字符串内容。操作符把字符串的每个元素视为单个 UTF-16 代码单元进行解释。但是,ECMAScript 并不约束这些代码单元的值或这些代码单元之间的关系,因此进一步将字符串内容解释为 UTF-16 中编码的 Unicode 代码点序列的操作必须考虑格式不对的子序列。此类操作使用如下规则对每个代码单元特殊处理,使其数值范围在 0xD800 到 0xDBFF(Unicode 标准定义为 首代理,或者更正式的 高代理码元)或范围 0xDC00 到 0xDFFF(定义为尾代理,或者更正式的低代理码元):

  • 不是 首代理 也不是 尾代理 的码元被解释为具有相同值的码点。
  • 两个码元序列,其第一个码元 c1 是一个 首代理,第二个码元 c2 是一个 尾代理, 这样的两个码元,被称为代理对, 被解释为一个值为 (c1 - 0xD800) × 0x400 + (c2 - 0xDC00) + 0x10000 的码点。(见 10.1.2)
  • 一个 首代理 或者 尾代理,但不是一个代理对的一部分的码元被解释为具有相同值的码点。

函数 String.prototype.normalize (see 21.1.3.12) 可以显式地标准化一个字符串值. String.prototype.localeCompare (see 21.1.3.10) 在内部规范化字符串值,但没有其他操作隐式规范化它们运行的字符串。只有明确指定为语言或区域设置敏感的操作才会生成对语言敏感的结果。

Note

这种设计背后的理由是尽可能的保持 String 的实现简单和高效。 如果 ECMAScript 源文本符合 Normalized Form C,只要它们不包含任何 Unicode 转义序列,则字符串字面量保证也是标准化的。

在本规范中,短语"the string-concatenation of A,B,..."表示字符串代码单元的序列是每个参数的代码单元的连接。

6.1.5 Symbol 类型

Symbol 类型是所有可以用于作为 Object 属性 key 值的非字符串值的集合。(6.1.7)。

每个可能的 Symbol 值都是唯一的和不可变的。

每个 Symbol 值永远地保持一个与之关联的叫做 [[Description]] 的值(它要么是 undefined 要么是一个 String 值)。

6.1.5.1 总所周知的 Symbol

总所周知的 Symbol 是那些被本规范中算法明确引用的内置 Symbol 值。它们通常被用作属性的 key,这些 key 的值作为规范的算法扩展点。除非另有说明,总所周知的 Symbol 的值被所有域(8.2)共享。

在本规范内,一个总所周知的 Symbol 值通过形如 @@name 的形式被引用,这里的 “name” 是表 Table 1 列出的值之一。

Table 1: Well-known Symbols
规范名称 [[Description]] 值和目的
@@asyncIterator "Symbol.asyncIterator" 返回对象的默认 AsyncIterator 的方法。 由 for-await-of 语句的语义调用。
@@hasInstance "Symbol.hasInstance" 确定构造函数对象是否识别对象为构造函数实例之一的方法。由 instanceof 运算符语义来调用。
@@isConcatSpreadable "Symbol.isConcatSpreadable" 一个 Boolean 值,如果为 true, 表示一个对象应该被 Array.prototype.concat 扁平化的加入到数组元素中。
@@iterator "Symbol.iterator" 返回一个对象的默认 Iterator 的方法。由 for-of 声明的语义来调用。
@@match "Symbol.match" 将字符串与正则表达式匹配的正则表达式方法。 由 String.prototype.match 方法调用。
@@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" 用于创建对象的默认字符串描述的 String 值属性。通过内置方法 Object.prototype.toString 访问。
@@unscopables "Symbol.unscopables" 一个对象值属性,其自身和继承的属性名是从相关对象的 with 环境绑定中排除的属性名。

6.1.6 Number 类型

Number 类型有 18437736874454810627 (即,264-253+3)个值,表示双精度 64 位格式的 IEEE 754-2008 值由 IEEE 二进制浮点数标准规定,除了 9007199254740990 (即,253-2)这个在 IEEE 标准中独特的 “Not-a-Number” 值,其在 ECMAScript 中表示为一个特殊的 NaN 值。(注意 NaN 值在程序中由 NaN 表达式产生)在某些实现中,外部代码可能能够检测各种 Not-a-Number 值之间的差异,但这种行为依赖于实现; 对于 ECMAScript 代码,所有的 NaN 值彼此是不可区分。

Note

在一个 Number 数值被存入之后,在一个 ArrayBuffer(见24.1) 或一个 SharedArrayBuffer(见24.2) 中可能观察到的位模式不一定和 ECMAScript 实现所使用的那个 Number 数值的内部表示相同。

还有另外两个特殊的值,叫做正无穷负无穷。 为了简洁起见,这些值分别由符号 +∞-∞ 表示。(请注意,这两个无穷数值由程序表达式 +Infinity(或 Infinity )和 -Infinity 产生。)

其他 18437736874454810624(即,264-253)个值称为有限值。 其中一半为正数,一般为负数;每个有限正数存在相同大小的对应负数。

注意其中有一个正零,一个负零。为了简洁,他们也分别用 +0-0 来说明。(注意这两个不同的 0,通过程序表达式 +0(或 0) 和 -0 产生。)

18437736874454810622(即 264-253-2)个有限非 0 值有两种:

其中 18428729675200069632 (即 264-254) 个值是标准的, 具有如下格式

s × m × 2e

其中 s 为 +1 或 -1,m 是一个小于 253 但大于等于 252 的整数,e 是从 -1074 到 971 的整数。

其余 9007199254740990 (即 253-2) 个值是非标准的, 有如下格式

s × m × 2e

其中 s 是 +1 或 -1 ,m 是小于 2 的 52 次方的正整数,e 是 -1074。

注意,大小不大于 253 的所有正整数和负整数可以在 Number 类型中表示(实际上,整数 0 具有两个表示,+0-0)。

如果一个有限的数值非零且用来表达它(上文两种形式之一)的整数 m 是奇数,则该数值有奇数意义。否则,它有偶数意义

在本规范中,当 x 表示一个精确的非零实数数学量(甚至可以是无理数,比如π)时,“the Number value for x” 意为,以下面的方式选择一个 Number 值。考虑 Number 类型中除了 -0 和两个被加入在数值类型中但不可呈现的值,21024 (+1 × 253 × 2971) 以及 -21024(-1 × 253 × 2971)的所有有限值的集合。选择此集合中值最接近 x 的一员。若集合中的两值近似相等,那么选择有偶数意义的那个;为此,21024-21024这两个超额值被认为有偶数意义。最终,若选择 21024 ,用 +∞ 替换它;若选择 -21024, 用 -∞ 替换它;若选择 +0,有且只有 x 小于零时,用 -0 替换它;其它任何被选取的值都不用改变。结果就是 x 的 Number 值。(此过程正是IEEE 754-2008“round to nearest, ties to even”模式对应的行为。)

某些 ECMAScript 运算符仅处理闭区间 -231231-1,或者 0 到 216-1 的整数。 这些操作符接收任意 Number 类型的值,首先会将它们转换成像上面提到的这些范围内的值。参考7.1的数字转换操作。

6.1.7 Object 类型

对象在逻辑上是属性的集合。每个属性都是一个数据属性或一个访问器属性:

  • 数据属性关联 key 值和一个 ECMAScript 语言值以及一组值为 Boolean 类型的特性。
  • 访问器属性关联 key 值和一个或两个访问器函数以及一组值为 Boolean 类型的特性。访问器函数用于存储或检索与该属性相关联的 ECMAScript 语言值。

属性使用 key 值来标识。一个属性的 key 值是 ECMAScript String 值或 Symbol 值。所有 String 值(包括空字符串) 和 Symbol 值作为属性的 key 都是有效的。属性名称是指属性的 key,其值为字符串。

一个值为 +0 或者一个 ≤ 253-1 的整数作为属性 key 字符串值的数字索引是一个以典型的数字 String(见 7.1.16)。一个数组索引是范围在 +0 ≤ i < 232-1 的整数。

属性的 key 用来访问属性以及其值。属性有两种访问方式:getset ,分别对应值的检索和赋值。通过 get 和 set 可访问的属性既包括直接属于的自身属性,也包括通过继承关系由其它相关对象提供的继承属性。继承属性也可能是另一个对象的自身属性或者继承属性。对象的每个自身属性必须有一个与对象的其他自身属性 key 值不同 key 值。

所有的对象都是逻辑上的属性集合,但是在用于访问和操纵它们的属性的语义中存在多种形式的对象。普通对象是对象的最常见形式,拥有默认的对象语义。奇异对象是指其属性语义与默认语义的各个方面都有区别的对象。

6.1.7.1 属性特性

在本规范中特性用来定义和解释对象属性的状态。数据属性 key 值与表Table 2中列出的特性关联。

Table 2: Attributes of a Data Property
特性名称 值域 描述
[[Value]] 任何 ECMAScript 语言类型 get 访问检索到的属性值
[[Writable]] Boolean 如果为 false,尝试通过 [[Set]] 去改变属性的 [[Value]] 特性的 ECMAScript 代码将不会成功。
[[Enumerable]] Boolean 如果为 true, 这个属性被 for-in 枚举时将会是可枚举的(见13.7.5)。否则,这个属性就是不可枚举的。
[[Configurable]] Boolean 如果为 false,尝试删除这个属性,把这个属性改为访问器属性,或者改变它的的特性(除了修改 [[Value]],或修改 [[Writable]] 为 false 之外)都会失败。

访问器属性关联表Table 3中的列出一个值。

Table 3: Attributes of an Accessor Property
特性名称 值域 描述
[[Get]] Object | Undefined 如果这个值是一个对象,那么它必须是一个函数对象。在每次取值(get 访问该属性被执行)时,这个函数的内部 [[Call]] 方法(Table 6)将会以一个空 arguments 列表调用获取属性值。
[[Set]] Object | Undefined 如果这个值是一个对象,那么它必须是一个函数对象。在每次赋值(set 访问该属性被执行)时,这个函数的内部 [[Call]] 方法(Table 6)将会以一个包含分配的值为参数的 arguments 调用。内部方法 [[Set]] 应该会对后续的内部方法 [[Get]] 调用产生的返回值产生影响,但不是必须的。
[[Enumerable]] Boolean 如果为 true,这个属性被 for-in 枚举时将会是可枚举的(见13.7.5)。 否则,这个属性就是不可枚举的。
[[Configurable]] Boolean 如果为 false,任何尝试删除这个属性,把这个属性改为数据属性,或者改变它的其它特性的操作都会失败。

如果一个属性的特性的初始值没有被本规范显式地指定的,那么使用在表Table 4中定义的默认值。

Table 4: Default Attribute Values
特性名 默认值
[[Value]] undefined
[[Get]] undefined
[[Set]] undefined
[[Writable]] false
[[Enumerable]] false
[[Configurable]] false

6.1.7.2 对象的内部方法以及内部槽

在 ECMAScript 中,对象的实际语义是通过算法来调用内部方法指定的。在 ECMAScript 引擎中的每个对象都与一系列的定义它的运行时行为的内部方法相关联。这些内部方法不属于 ECMAScript 语言的一部分。本规范定义它们纯粹是为了说明目的。但是,在 ECMAScript 具体实现中的每个对象必须表现得与其相关关联的内部方法一致。其中确切的方式由实现者来决定。

内部方法名称是多态的。这意味着当一个通用内部方法被调用的时候,不同的对象值可能会执行不同的算法。调用内部方法实际的对象是这个调用 “target”。如果在运行时,实现的算法尝试使用一个对象不支持的内部方法,抛出一个TypeError异常。

内部槽对应于相关对象的内部状态,用于各种 ECMAScript 规范算法。内部槽不是对象的属性,也不会被继承。根据具体的内部槽规范,内部状态可能由任意 ECMAScript 语言类型的值或者指定的 ECMAScript 规范类型的值组成。除非另有指定,否则分配内部槽应作为创建一个对象的过程的部分,并且不应该动态地添加到对象上。除非另有指定,否则一个内部槽的初始值是 undefined。本规范内很多算法都会创建有内部槽的对象。然而,ECMAScript 语言不提供直接去访问一个对象内部槽的方法。

本规范内的内部方法和内部槽使用闭合的双方括号 [[]] 来标识。

Table 5 总结了本规范中适用于所有通过 ECMAScript 代码创建或者操作的对象的基本内部方法。每个对象必须有所有基本内部方法的算法。不过,对于那些方法不必所有的对象都用一样的算法。

Table 5 中的 “Signature” 列以及其它相似的表格描述了每个内部方法的调用模式。调用模式总是包含一个括起来的描述参数名的列表。如果一个参数名与 ECMAScript 类型的名字一样,则该名称描述了参数值的所需类型。如果一个内部方法显式地返回了一个值,则它的参数列表接着是一个 “→” 符号,以及返回值的类型名称。 在 “Signature” 列中使用的类型名称指向在6中定义的类型,以及一些附加的名称。 “any” 意味着这个值可以是任意的 ECMAScript 语言值。一个内部方法会隐式地返回一个 Completion Record。 除了它的参数,一个内部方法还总会访问调用这个方法的目标对象。

Table 5: Essential Internal Methods
Internal Method Signature Description
[[GetPrototypeOf]] ( ) Object | Null 确定为对象提供继承属性的对象。null 值表示没有继承属性。
[[SetPrototypeOf]] (Object | Null) Boolean 关联这个对象与提供继承属性的对象。传递 null 表示没有继承属性。返回 true 表示操作成功完成,返回 false 表示操作失败。
[[IsExtensible]] ( ) Boolean 决定是否允许添加额外的属性到这个对象上。
[[PreventExtensions]] ( ) Boolean 控制一个新的属性是否能加到这个对象上。返回 true 表示操作成功,返回 false 表示操作失败。
[[GetOwnProperty]] (propertyKey) Undefined | Property Descriptor 返回对象自身属性中 key 值为 propertyKey 的属性的属性描述符,如果没有这个属性返回undefined
[[DefineOwnProperty]] (propertyKey, PropertyDescriptor) Boolean 创建或者改变 key 值为 propertyKey 的自身属性状态为 PropertyDescriptor。返回 true 表示属性被成功创建/更新,返回 false 表示属性不能被创建/更新。
[[HasProperty]] (propertyKey) Boolean 返回一个 Boolean 值,代表这个对象自身或者继承了一个 key 值为 propertyKey 的属性。
[[Get]] (propertyKey, Receiver) any 返回这个对象里 key 值为 propertyKey 的属性的值。如果必须运行一些的 ECMAScript 代码来检索这个属性值,Receiver 就会作为解析代码时的 this 值。
[[Set]] (propertyKey, value, Receiver) Boolean 设置这个对象 key 值为 propertyKey 的属性的值为 value。如果必须运行一些的 ECMAScript 代码来检索这个属性值,Receiver 就会作为解析代码时的 this 值。返回 true 表示这个属性值已经设置,返回 false 表示不能被设置。
[[Delete]] (propertyKey) Boolean 移除这个对象 key 值为 propertyKey 的自身属性。 如果这个属性没有被移除,仍然存在,则返回 false。 如果属性被移除,或不存在,则返回 true
[[OwnPropertyKeys]] ( ) List of propertyKey 返回一个包含所有自身属性 key 值的 List

Table 6 总结了用来支持对象被作为函数调用的其他基础内部方法。 函数对象是支持内部方法 [[Call]] 的对象。构造器是一个支持 [[Construct]] 内部方法的对象。支持 [[Construct]] 的每个对象都必须支持 [[Call]]; 也就是说,每个构造器都必须是一个函数对象。 因此,构造器也可以称为构造函数构造函数对象

Table 6: Additional Essential Internal Methods of Function Objects
Internal Method Signature Description
[[Call]] (any, a List of any) any 执行这个对象相关联的代码。通过一个函数表达式来调用。通过调用表达式,传递给内部函数的 arguments 为一个 this 值,和一个包含传递给函数的参数列表,实现该内部方法的对象是可调用的
[[Construct]] (a List of any, Object) Object 创建一个对象。通过 new 或者 super 操作符调用。这个内部方法的第一个参数是一个包含操作符的参数的列表。第二个参数是 new 操作符初始化时应用的对象。实现这个内部方法的对象被称为构造函数。一个函数对象不一定是构造函数,这样的非构造函数的函数对象没有 [[Construct]] 内部方法。

这些普通对象和标准的怪异对象的基础内部方法语义在9指出。如果怪异对象的任何特定内部方法不被实现支持,那么在尝试使用时,必须抛出一个 TypeError 异常。

6.1.7.3 基本内部方法的不变量

ECMAScript 引擎中的内部方法必须符合以下指定的不变量列表。普通 ECMAScript 对象以及该规范中的标准怪异对象应保持这些不变量。ECMAScript Proxy 对象通过运行时检查 [[ProxyHandler]] 对象的陷阱调用结果的手段来保持这些不变量。

任何实现提供的怪异对象必须也保持这些不变量。违反这些不变量可能会导致 ECMAScript 代码出现不可预料的行为以及安全问题。然而,对于造成内存安全的违反不变量行为的实现决不能妥协。

实现不允许通过任何方式规避这些不变量。比如,通过提供替代接口来实现基本内部方法的功能而不强制执行他们的不变量。

定义:

  • 内部方法的 target 是调用这个内部方法的对象。
  • 如果 target 的 [[IsExtensible]] 内部方法返回值是 false 或者 [[PreventExtensions]] 内部方法返回值是 true,那么这个 target 是不可扩展的
  • 一个不存在的属性是指一个不可扩展的 target 的自身属性中不存在的属性。
  • 所有对 SameValue 的引用都是根据 SameValue 算法定义的。

[[GetPrototypeOf]] ( )

  • 返回的类型必须是 Object 或者 Null。
  • 如果 target 是不可扩展的,并且 [[GetPrototypeOf]] 返回了一个值 v,那么任何将来对 [[GetPrototypeOf]] 的调用都应该返回与 v 相同的 SameValue
Note 1

对象的原型链的长度应该是有限的(也就是说,从任意对象开始,递归地对结果应用 [[GetPrototypeOf]] 内置方法最终应该得到 null)。但是,如果原型链包含任何不使用 [[GetPrototypeOf]] 的普通对象定义的奇异对象,则此要求不强制作为对象级不变量。这样的环形原型链可能会在访问对象属性时产生无限循环。

[[SetPrototypeOf]] (V)

  • 返回的类型必须是 Boolean。
  • 如果 target 是不可扩展的,[[SetPrototypeOf]] 必须返回 false,除非 V 与 target 执行 [[GetPrototypeOf]] 内置方法的 SameValue 相同。

[[IsExtensible]] ( )

  • 返回的类型必须是 Boolean。
  • 如果 [[IsExtensible]] 返回 false,所有将来对 target 的 [[IsExtensible]] 内置方法调用都必须返回 false。

[[PreventExtensions]] ( )

  • 返回的类型必须是 Boolean。
  • 如果 [[PreventExtensions]] 返回 false,所有将来对 target 的 [[IsExtensible]] 内置方法的的调用都必须返回 false,并且此刻开始 target 被认为是不可扩展的。

[[GetOwnProperty]] (P)

  • 返回的类型必须是 Property Descriptor 或者 Undefined。
  • 如果返回的类型是 Property Descriptor,那么返回值必须是一个完整的 property descriptor (见6.2.5.6)。
  • 一个属性 P 被数据属性 Desc 描述,如果 Desc.[[Value]] 等于 v,且 Desc.[[Writable]] 以及 Desc.[[Configurable]] 都为 false,那么所有将来调用 [[GetOwnProperty]](P) 内置方法时,返回的 SameValue 必须是属性的 Desc.[[Value]]。
  • 如果 P 属性除了 [[Writable]] 特性,其他特性在将来可能变化,或者属性可能消失,那么 P 的 [[Configurable]] 特性必须为 true。
  • 如果 P 属性的 [[Writable]] 特性可能从 false 变为 true,那么 [[Configurable]] 特性必须为 true。
  • 如果对象是不可扩展的且 P 属性不存在,那么将来所有对 target 的 [[GetOwnProperty]] (P) 内置方法的调用必须描述 P 属性不存在(即 [[GetOwnProperty]] (P) 必须返回 undefined)。
Note 2

作为第三个不变量的推论,如果一个属性被描述为一个数据属性并且随着时间它可能返回不同的值,那么 Desc.[[Writable]] 和 Desc.[[Configurable]] 特性必须是 true,虽然没有机制通过其它内置方法去改变暴露出来的值。

[[DefineOwnProperty]] (P, Desc)

  • 返回的类型必须是 Boolean。
  • 如果 P 预先已经作为 target 的一个不可配置的自身属性被观察,那么 [[DefineOwnProperty]] 必须返回 false,除非满足一下条件之一:

    1. P 是一个不可配置的可写数据属性。一个不可配置的可写数据属性可以被转换为一个不可配置不可写的数据属性
    2. Desc 中的所有特性都是作为 P 属性特性的 SameValue
  • 如果 target 是不可配置的且 P 属性不存在,那么 [[DefineOwnProperty]] (P, Desc) 必须返回 false。也就是说,一个不可配置的 target 对象不能扩展新属性。

[[HasProperty]] ( P )

  • 返回的类型必须是 Boolean。
  • 如果 target 自身属性 P 预先已经作为一个不可配置的数据属性或者访问器属性被观察,[[HasProperty]] 必须返回 true。

[[Get]] (P, Receiver)

  • 如果 P,其值为 V,预先作为一个不可配置,不可写的 target 自身属性被观察,那么 [[GET]] 必须返回 SameValue
  • 如果 P,其 [[Get]] 特性为 undefined,预先作为一个不可配置的 target 自身访问器属性被观察,那么 [[Get]] 操作必须返回 undefined。

[[Set]] ( P, V, Receiver)

  • 返回的类型必须是 Boolean。
  • 如果 P 预先作为一个不可配置,不可写的 target 自身数据属性被观察,那么 [[Set]] 必须返回 false。除非 V 是 P 的 [[Value]] 特性的 SameValue
  • 如果 P,其 [[Set]] 特性为 undefined,预先作为一个不可配置的 target 自身访问器属性被观察,那么 [[Set]] 操作必须返回 false。

[[Delete]] ( P )

  • 返回的类型必须是 Boolean。
  • 如果 P 预先作为一个不可配置的 target 自身数据或访问器属性被观察,那么 [[Delete]] 必须返回 false。

[[OwnPropertyKeys]] ( )

  • 返回值必须是一个 List
  • 返回的列表不能包含任何重复的元素。
  • 返回的 List 的每个元素类型为 String 或者 Symbol。
  • 返回的 List 必须包含至少预先已经被观察的自身属性的所有不可配置的 key。
  • 如果对象是不可扩展的,那么返回的 List 必须只包含使用 [[GetOwnProperty]] 观察的对象所有属性的 key。

[[Construct]] ( )

  • 返回值类型必须是 Object。

6.1.7.4 总所周知的内部对象

总所周知的内联函数是在该规范中通过算法明确引用的内置对象,这些内置对象通常有特定域的不变量。除非特别指出,每个内部对象在每个领域通常对应一系列相似对象的集合。

在本规范中像 %name% 这样的引用意味着关联到相应的 name 域的内部对象。决定当前域以及他的内联函数在8.3描述。总所周知的内联函数在表Table 7列出。

Table 7: Well-known Intrinsic Objects
内在名称 全局名称 ECMAScript 语言关联
%Array% Array Array 构造函数 (22.1.1)
%ArrayBuffer% ArrayBuffer ArrayBuffer 构造函数 (24.1.2)
%ArrayBufferPrototype% ArrayBuffer.prototype %ArrayBuffer% prototype 数据属性的初始值
%ArrayIteratorPrototype% 数组迭代器对象的原型 (22.1.5)
%ArrayPrototype% Array.prototype %Array% prototype 数据属性的初始值 (22.1.3)
%ArrayProto_entries% Array.prototype.entries %ArrayPrototype% entries 数据属性的初始值 (22.1.3.4)
%ArrayProto_forEach% Array.prototype.forEach %ArrayPrototype% forEach 数据属性的初始值 (22.1.3.10)
%ArrayProto_keys% Array.prototype.keys %ArrayPrototype% keys 数据属性的初始值 (22.1.3.14)
%ArrayProto_values% Array.prototype.values %ArrayPrototype% values 数据属性的初始值 (22.1.3.30)
%AsyncFromSyncIteratorPrototype% The prototype of async-from-sync iterator objects (25.1.4)
%AsyncFunction% async 函数对象构造器 (25.7.1)
%AsyncFunctionPrototype% %AsyncFunction% prototype 数据属性的初始值
%AsyncGenerator% The initial value of the prototype property of %AsyncGeneratorFunction%
%AsyncGeneratorFunction% The constructor of async iterator objects (25.3.1)
%AsyncGeneratorPrototype% The initial value of the prototype property of %AsyncGenerator%
%AsyncIteratorPrototype% An object that all standard built-in async iterator objects indirectly inherit from
%Atomics% Atomics Atomics 对象 (24.4)
%Boolean% Boolean Boolean 构造函数 (19.3.1)
%BooleanPrototype% Boolean.prototype %Boolean% prototype 数据属性的初始值 (19.3.3)
%DataView% DataView DataView 构造函数 (24.3.2)
%DataViewPrototype% DataView.prototype %DataView% prototype 数据属性的初始值
%Date% Date Date 构造函数 (20.3.2)
%DatePrototype% Date.prototype %Date% prototype 数据属性的初始值
%decodeURI% decodeURI decodeURI 函数 (18.2.6.2)
%decodeURIComponent% decodeURIComponent decodeURIComponent 函数 (18.2.6.3)
%encodeURI% encodeURI encodeURI 函数 (18.2.6.4)
%encodeURIComponent% encodeURIComponent encodeURIComponent 函数 (18.2.6.5)
%Error% Error Error 构造函数 (19.5.1)
%ErrorPrototype% Error.prototype %Error% prototype 数据属性的初始值
%eval% eval eval 函数 (18.2.1)
%EvalError% EvalError EvalError 构造函数 (19.5.5.1)
%EvalErrorPrototype% EvalError.prototype %EvalError% prototype 属性的初始值
%Float32Array% Float32Array Float32Array 构造函数 (22.2)
%Float32ArrayPrototype% Float32Array.prototype %Float32Array% prototype 数据属性的初始值
%Float64Array% Float64Array Float64Array 构造函数 (22.2)
%Float64ArrayPrototype% Float64Array.prototype %Float64Array% prototype 数据属性的初始值
%Function% Function Function 构造函数 (19.2.1)
%FunctionPrototype% Function.prototype %Function% prototype 数据属性的初始值
%Generator% %GeneratorFunction% prototype 属性的初始值
%GeneratorFunction% generator 对象的构造函数 (25.2.1)
%GeneratorPrototype% %Generator% prototype 属性的初始值
%Int8Array% Int8Array Int8Array 构造函数 (22.2)
%Int8ArrayPrototype% Int8Array.prototype %Int8Array% prototype 数据属性的初始值
%Int16Array% Int16Array Int16Array 构造函数 (22.2)
%Int16ArrayPrototype% Int16Array.prototype %Int16Array% prototype 数据属性的初始值
%Int32Array% Int32Array Int32Array 构造函数 (22.2)
%Int32ArrayPrototype% Int32Array.prototype %Int32Array% prototype 数据属性的初始值
%isFinite% isFinite isFinite 函数 (18.2.2)
%isNaN% isNaN isNaN 函数 (18.2.3)
%IteratorPrototype% 所有标准内置迭代对象间接继承的对象
%JSON% JSON JSON 对象 (24.5)
%JSONParse% JSON.parse %JSON% parse 数据属性的初始值
%Map% Map Map 构造函数 (23.1.1)
%MapIteratorPrototype% Map 迭代器对象的原型 (23.1.5)
%MapPrototype% Map.prototype %Map% prototype 数据属性的初始值
%Math% Math Math 对象 (20.2)
%Number% Number Number 构造函数 (20.1.1)
%NumberPrototype% Number.prototype %Number% prototype 属性的初始值
%Object% Object Object 构造函数 (19.1.1)
%ObjectPrototype% Object.prototype %Object%. (19.1.3) prototype 数据属性的初始值
%ObjProto_toString% Object.prototype.toString %ObjectPrototype% (19.1.3.6) toString 数据属性的初始值
%ObjProto_valueOf% Object.prototype.valueOf %ObjectPrototype% (19.1.3.7) valueOf 数据属性的初始值
%parseFloat% parseFloat parseFloat 函数 (18.2.4)
%parseInt% parseInt parseInt 函数 (18.2.5)
%Promise% Promise Promise 构造函数 (25.6.3)
%PromisePrototype% Promise.prototype %Promise% prototype 数据属性的初始值
%PromiseProto_then% Promise.prototype.then The initial value of the then data property of %PromisePrototype% (25.6.5.4)
%Promise_all% Promise.all The initial value of the all data property of %Promise% (25.6.4.1)
%Promise_reject% Promise.reject The initial value of the reject data property of %Promise% (25.6.4.4)
%Promise_resolve% Promise.resolve The initial value of the resolve data property of %Promise% (25.6.4.5)
%Proxy% Proxy Proxy 构造函数 (26.2.1)
%RangeError% RangeError RangeError 构造函数 (19.5.5.2)
%RangeErrorPrototype% RangeError.prototype %RangeError% prototype 属性的初始值
%ReferenceError% ReferenceError ReferenceError 构造函数 (19.5.5.3)
%ReferenceErrorPrototype% ReferenceError.prototype %ReferenceError% prototype 属性的初始值
%Reflect% Reflect Reflect 对象 (26.1)
%RegExp% RegExp RegExp 构造函数 (21.2.3)
%RegExpPrototype% RegExp.prototype %RegExp% prototype 数据属性的初始值
%Set% Set Set 构造函数 (23.2.1)
%SetIteratorPrototype% Set 迭代器对象的原型 (23.2.5)
%SetPrototype% Set.prototype %Set% prototype 数据属性的初始值
%SharedArrayBuffer% SharedArrayBuffer SharedArrayBuffer 构造函数 (24.2.2)
%SharedArrayBufferPrototype% SharedArrayBuffer.prototype %SharedArrayBuffer% prototype 数据属性的初始值
%String% String String 构造函数 (21.1.1)
%StringIteratorPrototype% String 迭代器对象的原型 (21.1.5)
%StringPrototype% String.prototype %String% prototype 数据属性的初始值
%Symbol% Symbol Symbol 构造函数 (19.4.1)
%SymbolPrototype% Symbol.prototype %Symbol% prototype 数据属性的初始值 (19.4.3)
%SyntaxError% SyntaxError SyntaxError 构造函数 (19.5.5.4)
%SyntaxErrorPrototype% SyntaxError.prototype %SyntaxError% prototype 属性的初始值
%ThrowTypeError% 一个函数对象,无条件的抛出一个新 %TypeError% 实例
%TypedArray% 所有数组类型构造器的超类 (22.2.1)
%TypedArrayPrototype% %TypedArray% `prototype 属性的初始值
%TypeError% TypeError TypeError 构造函数 (19.5.5.5)
%TypeErrorPrototype% TypeError.prototype %TypeError% prototype 属性的初始值
%Uint8Array% Uint8Array Uint8Array 构造函数 (22.2)
%Uint8ArrayPrototype% Uint8Array.prototype %Uint8Array% prototype 数据属性的初始值
%Uint8ClampedArray% Uint8ClampedArray Uint8ClampedArray 构造函数 (22.2)
%Uint8ClampedArrayPrototype% Uint8ClampedArray.prototype %Uint8ClampedArray% prototype 数据属性的初始值
%Uint16Array% Uint16Array Uint16Array 构造函数 (22.2)
%Uint16ArrayPrototype% Uint16Array.prototype %Uint16Array% prototype 数据属性的初始值
%Uint32Array% Uint32Array Uint32Array 构造函数 (22.2)
%Uint32ArrayPrototype% Uint32Array.prototype %Uint32Array% prototype 数据属性的初始值
%URIError% URIError URIError 构造函数 (19.5.5.6)
%URIErrorPrototype% URIError.prototype %URIError% prototype 属性的初始值
%WeakMap% WeakMap WeakMap 构造函数 (23.3.1)
%WeakMapPrototype% WeakMap.prototype %WeakMap% prototype 数据属性的初始值
%WeakSet% WeakSet WeakSet 构造函数 (23.4.1)
%WeakSetPrototype% WeakSet.prototype %WeakSet% prototype 数据属性的初始值

6.2 ECMAScript规范类型

规范类型对应那些在算法中用来描述 ECMAScript 语言结构以及 ECMAScript 语言类型语义的元数据。 规范类型包括 ReferenceListCompletionProperty DescriptorLexical EnvironmentEnvironment Record,以及 Data Block。规范类型值是规范中才有的,在一个 ECMAScript 实现中不必对应任何特定的实体。规范类型值可以用来描述 ECMAScript 表达式解析后的中间结果,但是这些值不应该作为 ECMAScript 变量的对象属性或者值储存。

6.2.1 List 以及 Record 规范类型

List 类型用来解释在 new 表达式,函数调用,以及其它需要一个简单的有序的值的 list 的算法中的参数列表(见12.3.6)的求值,List 类型的值是包含单个值的列表元素的简单有序序列。这些序列可能是任意长度。列表的元素可以通过使用从 0 开始的索引随机访问。为了方便起见,可以使用类似数组的语法来访问 List 元素。 例如,arguments[2] 简短的表示 arguments List 的第三个元素。

在规范中为了方便,一个字面量语法被用来表达一个新 List 值。 如 « 1, 2 » 定义一个新 List 值,它拥有两个元素,每个元素被初始化为一个特定的值。一个空的 List 值可以用 « » 表示。

Record 类型用来描述在该规范中的算法内的数据聚合。一个 Record 类型值包含一个或多个命名字段。每个字段的值是一个 ECMAScript 值或者通过由与 Record 类型相关联的名称代表的抽象值。字段名称始终用双括号括起来,例如 [[Value]]。

在规范中为了方便,使用类似对象字面量的语法来表示一个 Record 值。 如 { [[Field1]]: 42, [[Field2]]: false, [[Field3]]: empty } 定义一个拥有3个字段的 Record 值。每个字段被初始化为一个特定的值。字段名称顺序不重要。任何未明确列出的字段都被视为不存在。

在规范文本和算法中,点记号可以用于指代记录值的特定字段。例如,如果 R 是上一段所示的记录,则 R.[[Field2]] 是 “R 中名称为 [[Field2]] 的字段 ” 的缩写。

应该命名常用记录字段组合的模式, 并且该名称可以用作Record字面量的前缀,以标识特定类型聚合的描述。 例如:PropertyDescriptor { [[Value]]: 42,[[Writable]]: false,[[Configurable]]: true }。

6.2.2 Set 和 Relation 规范类型

Set 类型被用来解释在内存模型中无序元素的集合。Set 类型的值是简单的元素的集合,其中没有任何元素出现超过一次。元素可以从 Set 中添加或者删除。不同的 Set 可以合并,相交或者相减。

Relation 类型被用来解释在 Set 上的约束。一个关系类型的值是它的的值域中有序对的集合。例如,一个在 event 上的关系是一个有序的的 event 对的集合。对于一个关系 R 以及在 R 的值域中的两个值 aba R b 是有序对 (a, b) 是 R 的成员的简写。当 Relation 满足这些条件的最小 Relation 时,Relation 对于某些条件是最小的。

严格偏序是指一个 Relation 值 R 满足如下条件。

  • 对于R值域中的 abc

    • a R a 不成立,且
    • 如果 a R b 并且 b R c 成立,那么 a R c 成立。
Note 1

上述两种关系的特性被称为自反性和传递性。

严格全序是指一个 Relation 值 R 满足如下条件。

  • R 值域中的 abc

    • a 全等于 ba R bb R a,且
    • a R a 不成立,且
    • 如果 a R b 同时 b R c,那么 a R c
Note 2

上述三种关系的特性,按顺序被称为完全性,自反性,传递性

6.2.3 Completion Record 规范类型

Completion 类型是一个用来解释运行时数值和控制流传播的 Record,如执行非局部转移控制语句(breakcontinuereturnthrow)的行为。

Completion 类型值是字段名为表Table 8中的Record值。这些值被称为Completion Record

Table 8: Completion Record Fields
字段名 意义
[[Type]] normalbreakcontinuereturnthrow 之一 结束发生的完成类型
[[Value]] 任何 ECMAScript 语言值或 empty 产生的值
[[Target]] 任何 ECMAScript 字符串或 empty 用于定向控制传输的目标标签。

术语 “异常结束” 是指 [[Type]] 值为除 normal 之外的值。

6.2.3.1 Await

Algorithm steps that say

  1. Let completion be Await(promise).

mean the same thing as:

  1. Let asyncContext be the running execution context.
  2. Let promiseCapability be ! NewPromiseCapability(%Promise%).
  3. Perform ! Call(promiseCapability.[[Resolve]], undefined, « promise »).
  4. Let stepsFulfilled be the algorithm steps defined in Await Fulfilled Functions.
  5. Let onFulfilled be CreateBuiltinFunction(stepsFulfilled, « [[AsyncContext]] »).
  6. Set onFulfilled.[[AsyncContext]] to asyncContext.
  7. Let stepsRejected be the algorithm steps defined in Await Rejected Functions.
  8. Let onRejected be CreateBuiltinFunction(stepsRejected, « [[AsyncContext]] »).
  9. Set onRejected.[[AsyncContext]] to asyncContext.
  10. Let throwawayCapability be ! NewPromiseCapability(%Promise%).
  11. Set throwawayCapability.[[Promise]].[[PromiseIsHandled]] to true.
  12. Perform ! PerformPromiseThen(promiseCapability.[[Promise]], onFulfilled, onRejected, throwawayCapability).
  13. Remove asyncContext from the execution context stack and restore the execution context that is at the top of the execution context stack as the running execution context.
  14. Set the code evaluation state of asyncContext such that when evaluation is resumed with a Completion completion, the following steps of the algorithm that invoked Await will be performed, with completion available.

where all variables in the above steps, with the exception of completion, are ephemeral and visible only in the steps pertaining to Await.

Note

Await can be combined with the ? and ! prefixes, so that for example

  1. Let value be ? Await(promise).

means the same thing as:

  1. Let value be Await(promise).
  2. ReturnIfAbrupt(value).

6.2.3.1.1 Await Fulfilled Functions

An Await fulfilled function is an anonymous built-in function that is used as part of the Await specification device to deliver the promise fulfillment value to the caller as a normal completion. Each Await fulfilled function has an [[AsyncContext]] internal slot.

When an Await fulfilled function F is called with argument value, the following steps are taken:

  1. Let asyncContext be F.[[AsyncContext]].
  2. Let prevContext be the running execution context.
  3. Suspend prevContext.
  4. Push asyncContext onto the execution context stack; asyncContext is now the running execution context.
  5. Resume the suspended evaluation of asyncContext using NormalCompletion(value) as the result of the operation that suspended it.
  6. Assert: When we reach this step, asyncContext has already been removed from the execution context stack and prevContext is the currently running execution context.
  7. Return undefined.

The length property of an Await fulfilled function is 1.

6.2.3.1.2 Await Rejected Functions

An Await rejected function is an anonymous built-in function that is used as part of the Await specification device to deliver the promise rejection reason to the caller as an abrupt throw completion. Each Await rejected function has an [[AsyncContext]] internal slot.

When an Await rejected function F is called with argument reason, the following steps are taken:

  1. Let asyncContext be F.[[AsyncContext]].
  2. Let prevContext be the running execution context.
  3. Suspend prevContext.
  4. Push asyncContext onto the execution context stack; asyncContext is now the running execution context.
  5. Resume the suspended evaluation of asyncContext using ThrowCompletion(reason) as the result of the operation that suspended it.
  6. Assert: When we reach this step, asyncContext has already been removed from the execution context stack and prevContext is the currently running execution context.
  7. Return undefined.

The length property of an Await rejected function is 1.

6.2.3.2 NormalCompletion

抽象操作 NormalCompletion 具有单一 argument,如:

  1. Return NormalCompletion(argument).

Is a shorthand that is defined as follows:

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

6.2.3.3 ThrowCompletion

The abstract operation ThrowCompletion with a single argument, such as:

  1. Return ThrowCompletion(argument).

是下面定义的简写:

  1. Return Completion{[[Type]]: throw, [[Value]]: argument, [[Target]]: empty}.

6.2.3.4 UpdateEmpty ( completionRecord, value )

抽象操作 UpdateEmpty 有参数 completionRecordvalue,他的执行步骤如下:

  1. Assert: If completionRecord.[[Type]] is either return or throw, then completionRecord.[[Value]] is not empty.
  2. If completionRecord.[[Value]] is not empty, return Completion(completionRecord).
  3. Return Completion { [[Type]]: completionRecord.[[Type]], [[Value]]: value, [[Target]]: completionRecord.[[Target]] }.

6.2.4 Reference 规范类型

Note

Reference 类型用于解释如 deletetypeof,分配操作,super 关键字以及其他语言功能的操作的行为。例如,分配一个左操作数预计将产生一个引用

一个 Reference 是一个解析后的名称或者属性组合。一个 Reference 包含3个组件,基值组件,引用名组件,以及一个 Boolean 值的严格引用标志。一个基值组件可以是 undefined,Object, Boolean,String,Symbol,Number, 或 Environment Record。一个基值组件为 undefined 表示 Reference 解析为一个组合。引用名组件是一个 String,或 Symbol。

一个 Super Reference 是指,用于表示使用 super 关键字表示一个名称组合的 Reference。一个 Super Reference 有一个额外的 thisValue 组件,且他的基值组件永远不会是一个 Environment Record

以下抽象操作在本规范中用于操作引用:

6.2.4.1 GetBase ( V )

  1. Assert: Type(V) is Reference.
  2. Return the base value component of V.

6.2.4.2 GetReferencedName ( V )

  1. Assert: Type(V) is Reference.
  2. Return the referenced name component of V.

6.2.4.3 IsStrictReference ( V )

  1. Assert: Type(V) is Reference.
  2. Return the strict reference flag of V.

6.2.4.4 HasPrimitiveBase ( V )

  1. Assert: Type(V) is Reference.
  2. If Type(V's base value component) is Boolean, String, Symbol, or Number, return true; otherwise return false.

6.2.4.5 IsPropertyReference ( V )

  1. Assert: Type(V) is Reference.
  2. If either the base value component of V is an Object or HasPrimitiveBase(V) is true, return true; otherwise return false.

6.2.4.6 IsUnresolvableReference ( V )

  1. Assert: Type(V) is Reference.
  2. If the base value component of V is undefined, return true; otherwise return false.

6.2.4.7 IsSuperReference ( V )

  1. Assert: Type(V) is Reference.
  2. If V has a thisValue component, return true; otherwise return false.

6.2.4.8 GetValue ( V )

  1. ReturnIfAbrupt(V).
  2. If Type(V) is not Reference, return V.
  3. Let base be GetBase(V).
  4. If IsUnresolvableReference(V) is true, throw a ReferenceError exception.
  5. If IsPropertyReference(V) is true, then
    1. If HasPrimitiveBase(V) is true, then
      1. Assert: In this case, base will never be undefined or null.
      2. Set base to ! ToObject(base).
    2. Return ? base.[[Get]](GetReferencedName(V), GetThisValue(V)).
  6. Else base must be an Environment Record,
    1. Return ? base.GetBindingValue(GetReferencedName(V), IsStrictReference(V)) (see 8.1.1).
Note

在步骤 5.a.ii 中创建的对象在上面抽象方法和普通对象 [[GET]] 内部方法 之外是不可访问的。实现可以选择避免实际创建对象。

6.2.4.9 PutValue ( V, W )

  1. ReturnIfAbrupt(V).
  2. ReturnIfAbrupt(W).
  3. If Type(V) is not Reference, throw a ReferenceError exception.
  4. Let base be GetBase(V).
  5. If IsUnresolvableReference(V) is true, then
    1. If IsStrictReference(V) is true, then
      1. Throw a ReferenceError exception.
    2. Let globalObj be GetGlobalObject().
    3. Return ? Set(globalObj, GetReferencedName(V), W, false).
  6. Else if IsPropertyReference(V) is true, then
    1. If HasPrimitiveBase(V) is true, then
      1. Assert: In this case, base will never be undefined or null.
      2. Set base to ! ToObject(base).
    2. Let succeeded be ? base.[[Set]](GetReferencedName(V), W, GetThisValue(V)).
    3. If succeeded is false and IsStrictReference(V) is true, throw a TypeError exception.
    4. Return.
  7. Else base must be an Environment Record,
    1. Return ? base.SetMutableBinding(GetReferencedName(V), W, IsStrictReference(V)) (see 8.1.1).
Note

在步骤 6.a.ii 中创建的对象在上面抽象方法和普通对象 [[SET]] 内部方法 之外是不可访问的。实现可以选择避免实际创建对象。

6.2.4.10 GetThisValue ( V )

  1. Assert: IsPropertyReference(V) is true.
  2. If IsSuperReference(V) is true, then
    1. Return the value of the thisValue component of the reference V.
  3. Return GetBase(V).

6.2.4.11 InitializeReferencedBinding ( V, W )

  1. ReturnIfAbrupt(V).
  2. ReturnIfAbrupt(W).
  3. Assert: Type(V) is Reference.
  4. Assert: IsUnresolvableReference(V) is false.
  5. Let base be GetBase(V).
  6. Assert: base is an Environment Record.
  7. Return base.InitializeBinding(GetReferencedName(V), W).

6.2.5 Property Descriptor 规范类型

Property Descriptor 类型用来解释对象属性的特性的操作和具体化。Property Descriptor 的值为 Record 类型。每个字段的名称都是一个特性名称,其值是 6.1.7.1 相应的特性值。另外,任何字段都可以存在或不存在。在本规范中用于标记 Property Descriptor 记录的字面量描述是 “PropertyDescriptor”。

Property Descriptor 值可以根据某些字段的存在或使用进一步分类为数据 Property Descriptor 和访问器 Property Descriptor。包含字段 [[Value]] 或 [[Writable]] 的是数据 Property Descriptor。包含字段 [[Get]] 或 [[Set]] 的是访问器 Property Descriptor。所有的 Property Descriptor 都可能包含 [[Enumerable]],[[Configurable]] 字段名。一个 Property Descriptor 值可能不会同时为一个数据 Property Descriptor 和一个访问器 Property Descriptor。然而,也不一定,一个通用 Property Descriptor 是一个既不是数据 Property Descriptor 也不是访问器 Property Descriptor 的 Property Descriptor值。一个完全填充的 Property Descriptor 既是一个数据 Property Descriptor 也是一个访问器 Property Descriptor, 他有所有符合表 Table 2Table 3 定义的属性特性字段。

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

6.2.5.1 IsAccessorDescriptor ( Desc )

当用 Property Descriptor Desc 作为参数调用抽象操作 IsAccessorDescriptor 时,采取以下步骤:

  1. If Desc is undefined, return false.
  2. If both Desc.[[Get]] and Desc.[[Set]] are absent, return false.
  3. Return true.

6.2.5.2 IsDataDescriptor ( Desc )

当用 Property Descriptor Desc 作为参数调用抽象操作 IsDataDescriptor 时,采取以下步骤:

  1. If Desc is undefined, return false.
  2. If both Desc.[[Value]] and Desc.[[Writable]] are absent, return false.
  3. Return true.

6.2.5.3 IsGenericDescriptor ( Desc )

当用 Property Descriptor Desc 作为参数调用抽象操作 IsGenericDescriptor 时,采取以下步骤:

  1. If Desc is undefined, return false.
  2. If IsAccessorDescriptor(Desc) and IsDataDescriptor(Desc) are both false, return true.
  3. Return false.

6.2.5.4 FromPropertyDescriptor ( Desc )

当用Property Descriptor Desc作为参数调用抽象操作 FromPropertyDescriptor 时,采取以下步骤:

  1. If Desc is undefined, return undefined.
  2. Let obj be ObjectCreate(%ObjectPrototype%).
  3. Assert: obj is an extensible ordinary object with no own properties.
  4. If Desc has a [[Value]] field, then
    1. Perform CreateDataProperty(obj, "value", Desc.[[Value]]).
  5. If Desc has a [[Writable]] field, then
    1. Perform CreateDataProperty(obj, "writable", Desc.[[Writable]]).
  6. If Desc has a [[Get]] field, then
    1. Perform CreateDataProperty(obj, "get", Desc.[[Get]]).
  7. If Desc has a [[Set]] field, then
    1. Perform CreateDataProperty(obj, "set", Desc.[[Set]]).
  8. If Desc has an [[Enumerable]] field, then
    1. Perform CreateDataProperty(obj, "enumerable", Desc.[[Enumerable]]).
  9. If Desc has a [[Configurable]] field, then
    1. Perform CreateDataProperty(obj, "configurable", Desc.[[Configurable]]).
  10. Assert: All of the above CreateDataProperty operations return true.
  11. Return obj.

6.2.5.5 ToPropertyDescriptor ( Obj )

当用一个对象 Obj 作为参数调用抽象操作 ToPropertyDescriptor 时,采取以下步骤:

  1. If Type(Obj) is not Object, throw a TypeError exception.
  2. Let desc be a new Property Descriptor that initially has no fields.
  3. Let hasEnumerable be ? HasProperty(Obj, "enumerable").
  4. If hasEnumerable is true, then
    1. Let enum be ToBoolean(? Get(Obj, "enumerable")).
    2. Set desc.[[Enumerable]] to enum.
  5. Let hasConfigurable be ? HasProperty(Obj, "configurable").
  6. If hasConfigurable is true, then
    1. Let conf be ToBoolean(? Get(Obj, "configurable")).
    2. Set desc.[[Configurable]] to conf.
  7. Let hasValue be ? HasProperty(Obj, "value").
  8. If hasValue is true, then
    1. Let value be ? Get(Obj, "value").
    2. Set desc.[[Value]] to value.
  9. Let hasWritable be ? HasProperty(Obj, "writable").
  10. If hasWritable is true, then
    1. Let writable be ToBoolean(? Get(Obj, "writable")).
    2. Set desc.[[Writable]] to writable.
  11. Let hasGet be ? HasProperty(Obj, "get").
  12. If hasGet is true, then
    1. Let getter be ? Get(Obj, "get").
    2. If IsCallable(getter) is false and getter is not undefined, throw a TypeError exception.
    3. Set desc.[[Get]] to getter.
  13. Let hasSet be ? HasProperty(Obj, "set").
  14. If hasSet is true, then
    1. Let setter be ? Get(Obj, "set").
    2. If IsCallable(setter) is false and setter is not undefined, throw a TypeError exception.
    3. Set desc.[[Set]] to setter.
  15. If desc.[[Get]] is present or desc.[[Set]] is present, then
    1. If desc.[[Value]] is present or desc.[[Writable]] is present, throw a TypeError exception.
  16. Return desc.

6.2.5.6 CompletePropertyDescriptor ( Desc )

当用 Property Descriptor Desc 作为参数调用抽象操作 CompletePropertyDescriptor 时,采取以下步骤:

  1. Assert: Desc is a Property Descriptor.
  2. Let like be Record { [[Value]]: undefined, [[Writable]]: false, [[Get]]: undefined, [[Set]]: undefined, [[Enumerable]]: false, [[Configurable]]: false }.
  3. If IsGenericDescriptor(Desc) is true or IsDataDescriptor(Desc) is true, then
    1. If Desc does not have a [[Value]] field, set Desc.[[Value]] to like.[[Value]].
    2. If Desc does not have a [[Writable]] field, set Desc.[[Writable]] to like.[[Writable]].
  4. Else,
    1. If Desc does not have a [[Get]] field, set Desc.[[Get]] to like.[[Get]].
    2. If Desc does not have a [[Set]] field, set Desc.[[Set]] to like.[[Set]].
  5. If Desc does not have an [[Enumerable]] field, set Desc.[[Enumerable]] to like.[[Enumerable]].
  6. If Desc does not have a [[Configurable]] field, set Desc.[[Configurable]] to like.[[Configurable]].
  7. Return Desc.

6.2.6 Lexical Environment 和 Environment Record 规范类型

Lexical Environment and Environment Record 是用来解释在嵌套的函数和块中的名称解析行为。这些类型以及他们的操作在 8.1 中定义。

6.2.7 Data Blocks

Data Block 规范类型用来描述不同且可变的字节(8 bit)大小的数字值序列。一个 Data Block 值由初始值为 0,固定数量的字节构成。

在本规范中为了方便,可以使用类似数组的语法来访问一个 Data Block 值的各个字节。这些符号将 Data Block 值的这些字节表示为一个从 0 开始的索引队列。 例如,如果 db 是一个 5 字节的 Data Block 值,那么 db[2] 可以用来访问第三字节。

驻留在内存中,可以被多个代理并发引用的数据块被称为 Shared Data Block。一个 Shared Data Block 有一个 空地址 的标识(目的是平等检测 Shared Data Block 值): 它不依赖于所述块在任何进程中映射到的虚拟地址,而是用该块来表示内存中的位置集合。只有当两个块包含的位置集合相等时他们才相等。否则,他们地址集合的交集为空,他们是不相等的。最后,可以从 Data Block 区分 Shared Data Blocks。

Shared Data Block 的语义由内存模型中的 Shared Data Block 事件来定义。下方的抽象操作介绍了 Shared Data Block 事件,以及在内存模型上解析语义和事件语义的接口的行为。事件形成了一个候选执行,内存模型扮演了一个过滤器的角色。请查看内存模型来了解完整的语义。

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

下列抽象操作在本规范中用于对 Data Block 值进行操作:

6.2.7.1 CreateByteDataBlock ( size )

当用整数参数 size 调用抽象操作 CreateByteDataBlock 时,采取以下步骤:

  1. Assert: size≥0.
  2. Let db be a new Data Block value consisting of size bytes. If it is impossible to create such a Data Block, throw a RangeError exception.
  3. Set all of the bytes of db to 0.
  4. Return db.

6.2.7.2 CreateSharedByteDataBlock ( size )

当用整数参数 size 调用抽象操作 CreateByteDataBlock 时,采取以下步骤:

  1. Assert: size≥0.
  2. Let db be a new Shared Data Block value consisting of size bytes. If it is impossible to create such a Shared Data Block, throw a RangeError exception.
  3. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
  4. Let eventList be the [[EventList]] field of the element in execution.[[EventLists]] whose [[AgentSignifier]] is AgentSignifier().
  5. Let zero be « 0 ».
  6. For each index i of db, do
    1. Append WriteSharedMemory { [[Order]]: "Init", [[NoTear]]: true, [[Block]]: db, [[ByteIndex]]: i, [[ElementSize]]: 1, [[Payload]]: zero } to eventList.
  7. Return db.

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

抽象操作 CreateByteDataBlock 被调用时,采取以下步骤:

  1. Assert: fromBlock and toBlock are distinct Data Block or Shared Data Block values.
  2. Assert: fromIndex, toIndex, and count are integer values ≥ 0.
  3. Let fromSize be the number of bytes in fromBlock.
  4. Assert: fromIndex+countfromSize.
  5. Let toSize be the number of bytes in toBlock.
  6. Assert: toIndex+counttoSize.
  7. Repeat, while count>0
    1. If fromBlock is a Shared Data Block, then
      1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
      2. Let eventList be the [[EventList]] field of the element in execution.[[EventLists]] whose [[AgentSignifier]] is AgentSignifier().
      3. Let bytes be a List of length 1 that contains a nondeterministically chosen byte value.
      4. NOTE: In implementations, bytes is the result of a non-atomic read instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
      5. Let readEvent be ReadSharedMemory { [[Order]]: "Unordered", [[NoTear]]: true, [[Block]]: fromBlock, [[ByteIndex]]: fromIndex, [[ElementSize]]: 1 }.
      6. Append readEvent to eventList.
      7. Append Chosen Value Record { [[Event]]: readEvent, [[ChosenValue]]: bytes } to execution.[[ChosenValues]].
      8. If toBlock is a Shared Data Block, then
        1. Append WriteSharedMemory { [[Order]]: "Unordered", [[NoTear]]: true, [[Block]]: toBlock, [[ByteIndex]]: toIndex, [[ElementSize]]: 1, [[Payload]]: bytes } to eventList.
      9. Else,
        1. Set toBlock[toIndex] to bytes[0].
    2. Else,
      1. Assert: toBlock is not a Shared Data Block.
      2. Set toBlock[toIndex] to fromBlock[fromIndex].
    3. Increment toIndex and fromIndex each by 1.
    4. Decrement count by 1.
  8. Return NormalCompletion(empty).

7 抽象操作

这些操作不是 ECMAScript 语言的一部分;在这里定义他们只是为了规范 ECMAScript 语言的语义。另外,本规范中还定义了其他特定的抽象操作

7.1 类型转换

ECMAScript 语言根据需要会自动执行类型转换。为了解释清楚某些结构的语义,定义一组转换抽象操作是很有用的。转换抽象操作是多态的;他们可以接受一个任意 ECMAScript 类型的值。但是这些操作中没有使用其他相应的规范类型。

7.1.1 ToPrimitive ( input [ , PreferredType ] )

抽象操作 ToPrimitive 接受一个 input 参数和一个可选的 PreferredType 参数。ToPrimitive 负责把 input 参数转换为一个非对象类型。如果一个对象可以转换为多个原始类型,则应该根据可选提示 PreferredType 来判断转换的类型。根据以下算法进行转换:

  1. Assert: input is an ECMAScript language value.
  2. If Type(input) is Object, then
    1. If PreferredType is not present, let hint be "default".
    2. Else if PreferredType is hint String, let hint be "string".
    3. Else PreferredType is hint Number, let hint be "number".
    4. Let exoticToPrim be ? GetMethod(input, @@toPrimitive).
    5. If exoticToPrim is not undefined, then
      1. Let result be ? Call(exoticToPrim, input, « hint »).
      2. If Type(result) is not Object, return result.
      3. Throw a TypeError exception.
    6. If hint is "default", set hint to "number".
    7. Return ? OrdinaryToPrimitive(input, hint).
  3. Return input.
Note

当调用 ToPrimitive 没有提示参数时,通常表现和提示为 Number 类型一样。然而,对象可能通过定义一个 @@toPrimitive 方法,来覆盖这一行为。在本规范中的对象只有 Date 对象 (见 20.3.4.45) 和 Symbol(见 19.4.3.4) 会覆盖默认的 ToPrimitive 行为。Date 对象处理没有提示的调用就像提示为 String 类型一样。

7.1.1.1 OrdinaryToPrimitive ( O, hint )

当使用参数 Ohint 调用抽象操作 OrdinaryToPrimitive 时,执行以下步骤:

  1. Assert: Type(O) is Object.
  2. Assert: Type(hint) is String and its value is either "string" or "number".
  3. If hint is "string", then
    1. Let methodNames be « "toString", "valueOf" ».
  4. Else,
    1. Let methodNames be « "valueOf", "toString" ».
  5. For each name in methodNames in List order, do
    1. Let method be ? Get(O, name).
    2. If IsCallable(method) is true, then
      1. Let result be ? Call(method, O).
      2. If Type(result) is not Object, return result.
  6. Throw a TypeError exception.

7.1.2 ToBoolean ( argument )

抽象操作 ToBoolean 把参数 argument 转换为一个 Boolean 类型的值,见表 Table 9

Table 9: ToBoolean Conversions
参数类型 结果
Undefined 返回 false
Null 返回 false
Boolean 返回 argument
Number 如果 argument+0-0,or NaN,返回 false; 否则返回 true
String 如果 argument 是一个空字符串 (长度为0的字符串), 返回 false; 否则返回 true
Symbol 返回 true
Object 返回 true

7.1.3 ToNumber ( argument )

抽象操作argument 转换为一个 Number 类型的值,转换结果见表 Table 10

Table 10: ToNumber Conversions
参数类型 结果
Undefined 返回 NaN
Null 返回 +0
Boolean 如果 argumenttrue,返回 1。如果 argumentfalse,返回 +0
Number 返回 argument (不转换)。
String 见下面语法和转换算法。
Symbol 抛出一个 TypeError 异常。
Object

应用以下步骤:

  1. Let primValue be ? ToPrimitive(argument, hint Number).
  2. Return ? ToNumber(primValue).

7.1.3.1 应用于 String 类型的 ToNumber

应用 ToNumber 的字符串使用如下语法把字符串解释为一个 UTF-16 的编码码点 (6.1.4)。如果语法不能解释字符串为一个 StringNumericLiteral 终结符的扩展,那么 ToNumber 的结果是 NaN

Note 1

这个语法的终结符都由 Unicode BMP(Basic Multilingual Plane) 码点组成,所以,如果字符串包含任何首代理尾代理 码元,不管是配对还是未配对,那么 ToNumber 的结果就会是 NaN。

Syntax

StringNumericLiteral:::StrWhiteSpaceopt StrWhiteSpaceoptStrNumericLiteralStrWhiteSpaceopt StrWhiteSpace:::StrWhiteSpaceCharStrWhiteSpaceopt StrWhiteSpaceChar:::WhiteSpace LineTerminator StrNumericLiteral:::StrDecimalLiteral BinaryIntegerLiteral OctalIntegerLiteral HexIntegerLiteral StrDecimalLiteral:::StrUnsignedDecimalLiteral +StrUnsignedDecimalLiteral -StrUnsignedDecimalLiteral StrUnsignedDecimalLiteral:::Infinity DecimalDigits.DecimalDigitsoptExponentPartopt .DecimalDigitsExponentPartopt DecimalDigitsExponentPartopt

以上所有未明确定义的语法符号都在数字字面量词法定义(11.8.3)

Note 2

应该注意 StringNumericLiteralNumericLiteral 语法之间的一些区别:

7.1.3.1.1 运行时语义: MV

字符串到 Number 值的转换和一个的数字字面量 Number 值的确定总体上来说是相似的(见 11.8.3),但是也有一些细微的差别,因此在这里给出了转换一个 String 类型的数字字面量为一个 Number 类型的值的过程。这个数字由以下两个步骤确定:首先,从 String 类型的数字字面量导出数值(MV)由数学值(MV,以下简称数值);然后,这个数字像下面描述的那样舍入。很多语法符号的数值不在下面提供,在 11.8.3.1 定义。

一旦确定了字符串数字字面量确切的数值,它将被舍入为一个 Number 类型的值。如果数值为 0,那么它舍入的值为 +0,除非字符串数字字面量的第一个非空格码点是 "-",这种情况舍入值为 -0。否则,舍入的值必须为一个数字类型的数值(定义在 6.1.6 )除非这个字面量包含一个 StrUnsignedDecimalLiteral 并且拥有超过 20 位的有效数值,这种情况下,这个数值可以是由 0 替换字面量第 20 位后面的每个有效数字的字面量数值,也可以是在替换后从第 20 位数位递增的字面量数值。如果数字不是一个 ExponentPart 的部分,并且

  • 这个数字不是 0; 或者
  • 数字的左侧是一个非零的数字且他的右边是一个不在 ExponentPart 的非零数字。那么这个数字是有效的。

7.1.4 ToInteger ( argument )

抽象操作 ToInteger 把 argument 转换为整数数值。这个抽象操作算法如下:

  1. Let number be ? ToNumber(argument).
  2. If number is NaN, return +0.
  3. If number is +0, -0, +∞, or -∞, return number.
  4. Return the number value that is the same sign as number and whose magnitude is floor(abs(number)).

7.1.5 ToInt32 ( argument )

抽象操作 ToInt32 把 argument 转换为范围为 -231231-1的 232 个整数之一,这个抽象操作算法如下:

  1. Let number be ? ToNumber(argument).
  2. If number is NaN, +0, -0, +∞, or -∞, return +0.
  3. Let int be the mathematical value that is the same sign as number and whose magnitude is floor(abs(number)).
  4. Let int32bit be int modulo 232.
  5. If int32bit ≥ 231, return int32bit - 232; otherwise return int32bit.
Note

鉴于以上 ToInt32 的定义:

  • ToInt32 是等幂的: 其作用在同一个元素上产生的结果相同。
  • 对于任意 x,ToInt32(ToUint32(x)) 等于 ToInt32(x)。 (这是为了保证 +∞-∞ 会被映射为 +0。)
  • ToInt32 把 -0 映射为 +0.

7.1.6 ToUint32 ( argument )

抽象操作 ToUint32 将 argument 转换为 0 到 232-1 的 232 个整数之一。该抽象操作算法如下:

  1. Let number be ? ToNumber(argument).
  2. If number is NaN, +0, -0, +∞, or -∞, return +0.
  3. Let int be the mathematical value that is the same sign as number and whose magnitude is floor(abs(number)).
  4. Let int32bit be int modulo 232.
  5. Return int32bit.
Note

鉴于以上 ToUint32 的定义:

  • ToUint32 与ToInt32 只有第五步不同。
  • ToUint32 是等幂的: 其作用在同一个元素上产生的结果相同。
  • 对于任意 x,ToUint32(ToInt32(x)) 等于 ToUint32(x)。 (这是为了保证 +∞-∞ 会被映射为 +0。)
  • ToUint32 把 -0 映射为 +0

7.1.7 ToInt16 ( argument )

抽象操作 ToInt16 将 argument 转换为 -32768 到 32767 的 216 个整数之一。这个抽象操作算法如下:

  1. Let number be ? ToNumber(argument).
  2. If number is NaN, +0, -0, +∞, or -∞, return +0.
  3. Let int be the mathematical value that is the same sign as number and whose magnitude is floor(abs(number)).
  4. Let int16bit be int modulo 216.
  5. If int16bit ≥ 215, return int16bit - 216; otherwise return int16bit.

7.1.8 ToUint16 ( argument )

抽象操作 ToUint16 将 argument 转换为 0 到 216-1 的 216 个整数之一。这个抽象操作算法如下:

  1. Let number be ? ToNumber(argument).
  2. If number is NaN, +0, -0, +∞, or -∞, return +0.
  3. Let int be the mathematical value that is the same sign as number and whose magnitude is floor(abs(number)).
  4. Let int16bit be int modulo 216.
  5. Return int16bit.
Note

鉴于以上 ToUint16 的定义:

  • ToUint32 与 ToUint16 不同之处在于第四步时用 216 替换了 232
  • ToUint16 把 -0 映射为 +0.

7.1.9 ToInt8 ( argument )

抽象操作 ToInt8 负责将 argument 转换为 -128 到 127 的 28 个整数之一。这个抽象操作算法如下:

  1. Let number be ? ToNumber(argument).
  2. If number is NaN, +0, -0, +∞, or -∞, return +0.
  3. Let int be the mathematical value that is the same sign as number and whose magnitude is floor(abs(number)).
  4. Let int8bit be int modulo 28.
  5. If int8bit ≥ 27, return int8bit - 28; otherwise return int8bit.

7.1.10 ToUint8 ( argument )

抽象操作 ToUint8 负责将 argument 转换为 0 到 255 的 28 个整数之一。这个抽象操作算法如下:

  1. Let number be ? ToNumber(argument).
  2. If number is NaN, +0, -0, +∞, or -∞, return +0.
  3. Let int be the mathematical value that is the same sign as number and whose magnitude is floor(abs(number)).
  4. Let int8bit be int modulo 28.
  5. Return int8bit.

7.1.11 ToUint8Clamp ( argument )

抽象操作 ToUint8Clamp 负责将 argument 转换为 0 到 255 的 28 个整数之一。这个抽象操作算法如下:

  1. Let number be ? ToNumber(argument).
  2. If number is NaN, return +0.
  3. If number ≤ 0, return +0.
  4. If number ≥ 255, return 255.
  5. Let f be floor(number).
  6. If f + 0.5 < number, return f + 1.
  7. If number < f + 0.5, return f.
  8. If f is odd, return f + 1.
  9. Return f.
Note

与其他 ECMAScript 整数转换抽象操作不同。 ToUint8Clamp 对非整数值使用取整而不是截断,并且不会把 +∞ 转换为 0。

7.1.12 ToString ( argument )

抽象操作 ToString 负责将 argument 转换为一个 String 类型值,如下Table 11:

Table 11: ToString Conversions
参数类型 结果
Undefined 返回 "undefined".
Null 返回 "null".
Boolean

如果 argumenttrue, 返回 "true".

如果 argumentfalse, 返回 "false".

Number 返回 NumberToString(argument).
String 返回 argument.
Symbol 抛出一个 TypeError 异常.
Object

应用如下步骤:

  1. Let primValue be ? ToPrimitive(argument, hint String).
  2. Return ? ToString(primValue).

7.1.12.1 NumberToString ( m )

抽象操作 NumberToString 负责将一个 Number 类型值 m 转换为 String 类型,步骤如下:

  1. If m is NaN, return the String "NaN".
  2. If m is +0 or -0, return the String "0".
  3. If m is less than zero, return the string-concatenation of "-" and ! NumberToString(-m).
  4. If m is +∞, return the String "Infinity".
  5. Otherwise, let n, k, and s be integers such that k ≥ 1, 10k-1s < 10k, the Number value for s × 10n-k is m, and k is as small as possible. Note that k is the number of digits in the decimal representation of s, that s is not divisible by 10, and that the least significant digit of s is not necessarily uniquely determined by these criteria.
  6. If kn ≤ 21, return the string-concatenation of:
    • the code units of the k digits of the decimal representation of s (in order, with no leading zeroes)
    • n-k occurrences of the code unit 0x0030 (DIGIT ZERO)
  7. If 0 < n ≤ 21, return the string-concatenation of:
    • the code units of the most significant n digits of the decimal representation of s
    • the code unit 0x002E (FULL STOP)
    • the code units of the remaining k-n digits of the decimal representation of s
  8. If -6 < n ≤ 0, return the string-concatenation of:
    • the code unit 0x0030 (DIGIT ZERO)
    • the code unit 0x002E (FULL STOP)
    • -n occurrences of the code unit 0x0030 (DIGIT ZERO)
    • the code units of the k digits of the decimal representation of s
  9. Otherwise, if k = 1, return the string-concatenation of:
    • the code unit of the single digit of s
    • the code unit 0x0065 (LATIN SMALL LETTER E)
    • the code unit 0x002B (PLUS SIGN) or the code unit 0x002D (HYPHEN-MINUS) according to whether n-1 is positive or negative
    • the code units of the decimal representation of the integer abs(n-1) (with no leading zeroes)
  10. Return the string-concatenation of:
    • the code units of the most significant digit of the decimal representation of s
    • the code unit 0x002E (FULL STOP)
    • the code units of the remaining k-1 digits of the decimal representation of s
    • the code unit 0x0065 (LATIN SMALL LETTER E)
    • the code unit 0x002B (PLUS SIGN) or the code unit 0x002D (HYPHEN-MINUS) according to whether n-1 is positive or negative
    • the code units of the decimal representation of the integer abs(n-1) (with no leading zeroes)
Note 1

以下结论作为实现的参考可能是有用的,不过他们并不作为规范的要求。

  • 对于任何非 -0 的 Number 类型值 x,他的 ToNumber(ToString(x)) 结果恰好为 Number 值 x。
  • s 的最少有效数位并不总是由第五步中的要求列表唯一确定。
Note 2

对于提供了比上述转换规则更准确的实现,建议其中第五步参考下面的另一个版本:

  1. Otherwise, let n, k, and s be integers such that k ≥ 1, 10k-1s < 10k, the Number value for s × 10n-k is m, and k is as small as possible. If there are multiple possibilities for s, choose the value of s for which s × 10n-k is closest in value to m. If there are two such possible values of s, choose the one that is even. Note that k is the number of digits in the decimal representation of s and that s is not divisible by 10.
Note 3

David M. Gay 编写的二进制转换为十进制中关于浮点数的文章和代码对于 ECMAScript 实现者可能会有帮助:

Gay, David M. Correctly Rounded Binary-Decimal and Decimal-Binary Conversions. Numerical Analysis, Manuscript 90-10. AT&T Bell Laboratories (Murray Hill, New Jersey). November 30, 1990. 相关文章可以在
http://ampl.com/REFS/abstracts.html#rounding 找到. 相关代码在
http://netlib.sandia.gov/fp/dtoa.c
http://netlib.sandia.gov/fp/g_fmt.c ,这些代码也可以在其他 netlib 镜像网站找到。

7.1.13 ToObject ( argument )

抽象操作 ToObject 负责将 argument 转换为 Object 类型的值,见表Table 12

Table 12: ToObject Conversions
参数类型 结果
Undefined 抛出一个 TypeError 异常。
Null 抛出一个 TypeError 异常。
Boolean 返回一个内部槽 [[BooleanData]] 为 argument 的新 Boolean 对象。见 19.3 关于 Boolean 对象的描述。
Number 返回一个内部槽 [[NumberData]] 为 argument 的新 Number 对象。见 20.1 关于 Number 对象的描述。
String 返回一个内部槽 [[StringData]] 为 argument 的新 String 对象。见 21.1 关于 String 对象的描述。
Symbol 返回一个内部槽 [[SymbolData]] 为 argument 的新 Symbol 对象。见 19.4 关于 Symbol 对象的描述。
Object 返回 argument

7.1.14 ToPropertyKey ( argument )

抽象操作 ToPropertyKey 负责将 argument 转换为一个可用作属性 key 的值,其步骤如下:

  1. Let key be ? ToPrimitive(argument, hint String).
  2. If Type(key) is Symbol, then
    1. Return key.
  3. Return ! ToString(key).

7.1.15 ToLength ( argument )

抽象操作 ToLength 负责将 argument 转换为一个可用作类数组的长度的整数,其步骤如下:

  1. Let len be ? ToInteger(argument).
  2. If len+0, return +0.
  3. Return min(len, 253-1).

7.1.16 CanonicalNumericIndexString ( argument )

如果 argument 为是一可以通过 ToString 产生的数字字符串,或者是一个为 "-0" 的字符串,则抽象操作 CanonicalNumericIndexString 返回转换 argument 得到的一个数字。否则,返回 undefined。这个抽象操作算法如下:

  1. Assert: Type(argument) is String.
  2. If argument is "-0", return -0.
  3. Let n be ! ToNumber(argument).
  4. If SameValue(! ToString(n), argument) is false, return undefined.
  5. Return n.

一个规范的数字字符串是指 CanonicalNumericIndexString 抽象操作返回值不为 undefined 的字符串。

7.1.17 ToIndex ( value )

抽象操作 ToIndex 负责将 value 参数转换为一个有效的整数索引值。这个抽象操作算法如下:

  1. If value is undefined, then
    1. Let index be 0.
  2. Else,
    1. Let integerIndex be ? ToInteger(value).
    2. If integerIndex < 0, throw a RangeError exception.
    3. Let index be ! ToLength(integerIndex).
    4. If SameValueZero(integerIndex, index) is false, throw a RangeError exception.
  3. Return index.

7.2 测试与比较操作

7.2.1 RequireObjectCoercible ( argument )

抽象操作 RequireObjectCoercible 尝试使用 ToObjectargument 转换为一个对象,如果转换失败,则抛出一个错误,成功则返回 argument。如下表Table 13中定义的:

Table 13: RequireObjectCoercible Results
参数类型 结果
Undefined 抛出一个 TypeError 异常。
Null 抛出一个 TypeError 异常。
Boolean 返回 argument.
Number 返回 argument.
String 返回 argument.
Symbol 返回 argument.
Object 返回 argument.

7.2.2 IsArray ( argument )

抽象操作 IsArray 接受一个参数 argument,他的执行步骤如下:

  1. If Type(argument) is not Object, return false.
  2. If argument is an Array exotic object, return true.
  3. If argument is a Proxy exotic object, then
    1. If argument.[[ProxyHandler]] is null, throw a TypeError exception.
    2. Let target be argument.[[ProxyTarget]].
    3. Return ? IsArray(target).
  4. Return false.

7.2.3 IsCallable ( argument )

抽象操作 IsCallable 用于判断 argument 是否为一个拥有 [[call]] 内部方法的可调用函数,argument 必须是 ECMAScript 语言值。

  1. If Type(argument) is not Object, return false.
  2. If argument has a [[Call]] internal method, return true.
  3. Return false.

7.2.4 IsConstructor ( argument )

抽象操作 IsConstructor 用于判断 argument 是否为一个拥有 [[Construct]] 内部方法的函数对象argument 必须是 ECMAScript 语言值。

  1. If Type(argument) is not Object, return false.
  2. If argument has a [[Construct]] internal method, return true.
  3. Return false.

7.2.5 IsExtensible ( O )

抽象操作 IsExtensible 用于判断对象 O 是否可以添加新的属性,返回一个 Boolean 值。该抽象操作的执行步骤如下:

  1. Assert: Type(O) is Object.
  2. Return ? O.[[IsExtensible]]().

7.2.6 IsInteger ( argument )

抽象操作 IsInteger 用于判断 argument 是否为一个有限整数数值。

  1. If Type(argument) is not Number, return false.
  2. If argument is NaN, +∞, or -∞, return false.
  3. If floor(abs(argument)) ≠ abs(argument), return false.
  4. Return true.

7.2.7 IsPropertyKey ( argument )

抽象操作 IsPropertyKey 用于判断 argument 是否可用作为对象的属性的 key,argument 必须是一个 ECMAScript 语言值。

  1. If Type(argument) is String, return true.
  2. If Type(argument) is Symbol, return true.
  3. Return false.

7.2.8 IsRegExp ( argument )

参数为 argument抽象操作 IsRegExp 执行步骤如下:

  1. If Type(argument) is not Object, return false.
  2. Let matcher be ? Get(argument, @@match).
  3. If matcher is not undefined, return ToBoolean(matcher).
  4. If argument has a [[RegExpMatcher]] internal slot, return true.
  5. Return false.

7.2.9 IsStringPrefix ( p, q )

抽象操作 IsStringPrefix 确定字符串 p 是不是字符串 q 的前缀。

  1. Assert: Type(p) is String.
  2. Assert: Type(q) is String.
  3. If q can be the string-concatenation of p and some other String r, return true. Otherwise, return false.
  4. NOTE: Any String is a prefix of itself, because r may be the empty String.

7.2.10 SameValue ( x, y )

内部比较抽象操作 SameValue(x, y) 返回 truefalse,其中 xy 都是 ECMAScript 语言值。它将执行比较如下:

  1. If Type(x) is different from Type(y), return false.
  2. If Type(x) is Number, then
    1. If x is NaN and y is NaN, return true.
    2. If x is +0 and y is -0, return false.
    3. If x is -0 and y is +0, return false.
    4. If x is the same Number value as y, return true.
    5. Return false.
  3. Return SameValueNonNumber(x, y).
Note

这个算法在比较有符号的 0 以及比较 NaN 时和严格相等比较算法不同。

7.2.11 SameValueZero ( x, y )

内部比较抽象操作 SameValueZero(x, y) 返回 truefalse,其中 xy 都是ECMAScript语言值。 它将执行比较如下:

  1. If Type(x) is different from Type(y), return false.
  2. If Type(x) is Number, then
    1. If x is NaN and y is NaN, return true.
    2. If x is +0 and y is -0, return true.
    3. If x is -0 and y is +0, return true.
    4. If x is the same Number value as y, return true.
    5. Return false.
  3. Return SameValueNonNumber(x, y).
Note

SameValueZero 与 SameValue 仅在处理 +0-0 时不同

7.2.12 SameValueNonNumber ( x, y )

内部比较抽象操作 SameValueNonNumber(x, y) 返回 truefalse,其中 xy 都是 Number 值。它将执行比较如下:

  1. Assert: Type(x) is not Number.
  2. Assert: Type(x) is the same as Type(y).
  3. If Type(x) is Undefined, return true.
  4. If Type(x) is Null, return true.
  5. If Type(x) is String, then
    1. If x and y are exactly the same sequence of code units (same length and same code units at corresponding indices), return true; otherwise, return false.
  6. If Type(x) is Boolean, then
    1. If x and y are both true or both false, return true; otherwise, return false.
  7. If Type(x) is Symbol, then
    1. If x and y are both the same Symbol value, return true; otherwise, return false.
  8. If x and y are the same Object value, return true. Otherwise, return false.

7.2.13 抽象关系比较

比较x < yxy 都是 ECMAScript 语言值,将可能产生true, false, 或 undefined(表示其中至少有一个操作数为 NaN)。除了 xy 之外,算法会使用一个名为 LeftFirst 的 Boolean 类型标志,作为一个参数。这个标志用于控制对 xy 执行潜在可见副作用操作的顺序。这是有必要的,因为 ECMAScript 规定计算是从左向右的。LeftFirst 的默认值为 true,表示 x 参数相应表达式在 y 参数相应的表达式的左测。如果 LeftFirstfalse,则必须在 x 之前执行 y。具体比较执行如下:

  1. If the LeftFirst flag is true, then
    1. Let px be ? ToPrimitive(x, hint Number).
    2. Let py be ? ToPrimitive(y, hint Number).
  2. Else the order of evaluation needs to be reversed to preserve left to right evaluation,
    1. Let py be ? ToPrimitive(y, hint Number).
    2. Let px be ? ToPrimitive(x, hint Number).
  3. If Type(px) is String and Type(py) is String, then
    1. If IsStringPrefix(py, px) is true, return false.
    2. If IsStringPrefix(px, py) is true, return true.
    3. Let k be the smallest nonnegative integer such that the code unit at index k within px is different from the code unit at index k within py. (There must be such a k, for neither String is a prefix of the other.)
    4. Let m be the integer that is the numeric value of the code unit at index k within px.
    5. Let n be the integer that is the numeric value of the code unit at index k within py.
    6. If m < n, return true. Otherwise, return false.
  4. Else,
    1. NOTE: Because px and py are primitive values evaluation order is not important.
    2. Let nx be ? ToNumber(px).
    3. Let ny be ? ToNumber(py).
    4. If nx is NaN, return undefined.
    5. If ny is NaN, return undefined.
    6. If nx and ny are the same Number value, return false.
    7. If nx is +0 and ny is -0, return false.
    8. If nx is -0 and ny is +0, return false.
    9. If nx is +∞, return false.
    10. If ny is +∞, return true.
    11. If ny is -∞, return false.
    12. If nx is -∞, return true.
    13. If the mathematical value of nx is less than the mathematical value of ny—note that these mathematical values are both finite and not both zero—return true. Otherwise, return false.
Note 1

算法中的第三步和第七步不同是加法运算 + (12.8.3)使用逻辑与操作而不是使用逻辑或操作。

Note 2

字符串类型的比较使用码元值序列的简单词典排序。这里没有尝试使用 Unicode 规范定义的更复杂的,基于语义的字符或字符串相等,以及排序顺序进行比较。因此,根据 Unicode 标准在规范上相等的字符串值可能测试为不相等。实际上,该算法假设了两个值是已经标准化的值。另外还需注意,对于包含补充字符的字符串,UTF-16 码元值序列与普通码元值序列的词典排序是不同的。

7.2.14 抽象相等比较

比较 x == y,产生 truefalse,其中 xy 都是 ECMAScript 语言值。具体比较算法如下:

  1. If Type(x) is the same as Type(y), then
    1. Return the result of performing Strict Equality Comparison x === y.
  2. If x is null and y is undefined, return true.
  3. If x is undefined and y is null, return true.
  4. If Type(x) is Number and Type(y) is String, return the result of the comparison x == ! ToNumber(y).
  5. If Type(x) is String and Type(y) is Number, return the result of the comparison ! ToNumber(x) == y.
  6. If Type(x) is Boolean, return the result of the comparison ! ToNumber(x) == y.
  7. If Type(y) is Boolean, return the result of the comparison x == ! ToNumber(y).
  8. If Type(x) is either String, Number, or Symbol and Type(y) is Object, return the result of the comparison x == ToPrimitive(y).
  9. If Type(x) is Object and Type(y) is either String, Number, or Symbol, return the result of the comparison ToPrimitive(x) == y.
  10. Return false.

7.2.15 严格相等比较

比较 x === y,产生 truefalse,其中 xy 都是ECMAScript语言值。具体比较算法如下:

  1. If Type(x) is different from Type(y), return false.
  2. If Type(x) is Number, then
    1. If x is NaN, return false.
    2. If y is NaN, return false.
    3. If x is the same Number value as y, return true.
    4. If x is +0 and y is -0, return true.
    5. If x is -0 and y is +0, return true.
    6. Return false.
  3. Return SameValueNonNumber(x, y).
Note

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

7.3 对象具有的操作

7.3.1 Get ( O, P )

抽象操作 Get 用于检索对象特定属性的值。该操作接受两个参数 O, P,其中 O 是操作的对象,P 是对象的属性 key。该抽象操作执行以下步骤:

  1. Assert: Type(O) is Object.
  2. Assert: IsPropertyKey(P) is true.
  3. Return ? O.[[Get]](P, O).

7.3.2 GetV ( V, P )

抽象操作 GetV 用于检索一个 ECMAScript 语言值指定属性的值。如果这个 ECMAScript 值不是对象,则使用合适该值类型的属性包装器对象来执行属性的查找。使用参数 VP 调用操作([[Get]]),其中 V 是传入的 ECMAScript 值,P 是需要检索的属性 key。该抽象操作的执行步骤如下:

  1. Assert: IsPropertyKey(P) is true.
  2. Let O be ? ToObject(V).
  3. Return ? O.[[Get]](P, V).

7.3.3 Set ( O, P, V, Throw )

抽象操作 Set 用于设置对象的特定属性的值。该操作使用参数 OPVThrow 调用,其中 O 是被操作的对象,P 是制定的属性, V 是属性的新值,Throw 是一个 Boolean 类型的标志。该操作的执行步骤如下:

  1. Assert: Type(O) is Object.
  2. Assert: IsPropertyKey(P) is true.
  3. Assert: Type(Throw) is Boolean.
  4. Let success be ? O.[[Set]](P, V, O).
  5. If success is false and Throw is true, throw a TypeError exception.
  6. Return success.

7.3.4 CreateDataProperty ( O, P, V )

抽象操作 CreateDataProperty 用于给对象创建一个新的自身属性。这个操作使用参数 OPV 调用,其中 O 是被操作的对象,P 是属性 key 值,V 是属性的值。这个抽象操作执行以下步骤:

  1. Assert: Type(O) is Object.
  2. Assert: IsPropertyKey(P) is true.
  3. Let newDesc be the PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }.
  4. Return ? O.[[DefineOwnProperty]](P, newDesc).
Note

抽象操作创建一个和通过 ECMAScript 语言赋值运算符创建的属性相同特性的属性。通常,这个属性(开始)是不存在的。如果该属性存在并且是不可配置的,或者对象 O 是不可扩展的,则内置方法 [[DefineOwnProperty]] 将返回 false

7.3.5 CreateMethodProperty ( O, P, V )

抽象操作 CreateMethodProperty 用于给对象创建一个新的自身属性。接受参数 OPV,其中 O 是目标对象,P 是属性 key,V 是属性值。该操作的执行步骤如下:

  1. Assert: Type(O) is Object.
  2. Assert: IsPropertyKey(P) is true.
  3. Let newDesc be the PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
  4. Return ? O.[[DefineOwnProperty]](P, newDesc).
Note

这个抽象操作创建的属性和那些内部方法或者使用类定于语法定义的方法使用相同的默认特性。该抽象操作创建一个和通过 ECMAScript 语言赋值运算符创建的属性相同特性的属性。通常,这个属性(开始)是不存在的。如果该属性存在并且是不可配置的,或者对象 O 是不可扩展的,则内置方法 [[DefineOwnProperty]] 将返回 false

7.3.6 CreateDataPropertyOrThrow ( O, P, V )

抽象操作 CreateDataPropertyOrThrow 用于给对象自身添加一个新属性,如果更新属性的请求不能执行将抛出 TypeError 异常。接受参数 OPV,其中 O 是目标对象,P 是属性 key,V 是属性值。该操作的执行步骤如下:

  1. Assert: Type(O) is Object.
  2. Assert: IsPropertyKey(P) is true.
  3. Let success be ? CreateDataProperty(O, P, V).
  4. If success is false, throw a TypeError exception.
  5. Return success.
Note

这个抽象操作创建的属性和那些内部方法或者使用类定于语法定义的方法使用相同的默认特性。该抽象操作创建一个和通过 ECMAScript 语言赋值运算符创建的属性相同特性的属性。通常,这个属性(开始)是不存在的。如果该属性存在并且是不可配置的,或者对象 O 是不可扩展的,则内置方法 [[DefineOwnProperty]] 将返回 false

7.3.7 DefinePropertyOrThrow ( O, P, desc )

抽象操作 DefinePropertyOrThrow 通过调用对象内部方法 [[DefineOwnProperty]] 的方式定义一个自身属性,如果更新属性的请求不能执行将抛出 TypeError 异常。该操作接受参数 OPdesc,其中 O 是目标对象,P 是属性 key,desc 是属性的 Property Descriptor。该操作的执行步骤如下:

  1. Assert: Type(O) is Object.
  2. Assert: IsPropertyKey(P) is true.
  3. Let success be ? O.[[DefineOwnProperty]](P, desc).
  4. If success is false, throw a TypeError exception.
  5. Return success.

7.3.8 DeletePropertyOrThrow ( O, P )

抽象操作 DeletePropertyOrThrow 用于删除指定对象属性。如果属性是不可配置的将抛出(TypeError)异常。参数 O 表示目标对象,P 是指定需要删除的属性 key。该操作的执行步骤如下:

  1. Assert: Type(O) is Object.
  2. Assert: IsPropertyKey(P) is true.
  3. Let success be ? O.[[Delete]](P).
  4. If success is false, throw a TypeError exception.
  5. Return success.

7.3.9 GetMethod ( V, P )

抽象操作 GetMethod 用于从一个 ECMAScript 语言值获取指定属性的值,该值应该是一个函数。参数 V 表示一个被操作的 ECMAScript 语言值,P 表示指定的属性 key。该操作的执行步骤如下:

  1. Assert: IsPropertyKey(P) is true.
  2. Let func be ? GetV(V, P).
  3. If func is either undefined or null, return undefined.
  4. If IsCallable(func) is false, throw a TypeError exception.
  5. Return func.

7.3.10 HasProperty ( O, P )

抽象操作 HasProperty 用于确定一个对象是否拥有特定的属性。这个属性可以是自身的也可以是继承的。该抽象操作返回一个 Boolean 值。参数 O 表示目标对象,P 是指定的属性 key。该操作的执行步骤如下:

  1. Assert: Type(O) is Object.
  2. Assert: IsPropertyKey(P) is true.
  3. Return ? O.[[HasProperty]](P).

7.3.11 HasOwnProperty ( O, P )

抽象操作 HasOwnProperty 用于确定对象自身是否拥有特定的属性。返回一个 Boolean 值。参数 O 表示目标对象,P 是指定的属性 key。该操作的执行步骤如下:

  1. Assert: Type(O) is Object.
  2. Assert: IsPropertyKey(P) is true.
  3. Let desc be ? O.[[GetOwnProperty]](P).
  4. If desc is undefined, return false.
  5. Return true.

7.3.12 Call ( F, V [ , argumentsList ] )

抽象操作 Call 负责调用一个函数对象的 [[Call]] 内部方法。该操作接受一个函数对象 F,一个代表 [[Call]] 的 this 值的 ECMAScript 语言值 V,以及传递给内部方法的可选参数 argumentsList。如果 argument 没提供,则默认使用一个空的 List。该操作的执行步骤如下:

  1. If argumentsList is not present, set argumentsList to a new empty List.
  2. If IsCallable(F) is false, throw a TypeError exception.
  3. Return ? F.[[Call]](V, argumentsList).

7.3.13 Construct ( F [ , argumentsList [ , newTarget ]] )

抽象操作 Construct 用于调用函数对象内部方法 [[Construct]]。该抽象操作使用参数 F, 可选参数 argumentsList, 以及可选参数 newTarget。 其中 F 是一个函数对象. argumentsListnewTarget 是作为内部方法相应参数传递的值。 如果 argumentsList 未提供则默认使用一个空 List 作为其值。如果 newTarget 未提供,则使用 F 作为其值。该抽象操作执行步骤如下:

  1. If newTarget is not present, set newTarget to F.
  2. If argumentsList is not present, set argumentsList to a new empty List.
  3. Assert: IsConstructor(F) is true.
  4. Assert: IsConstructor(newTarget) is true.
  5. Return ? F.[[Construct]](argumentsList, newTarget).
Note

If newTarget is not present, this operation is equivalent to: new F(...argumentsList)

7.3.14 SetIntegrityLevel ( O, level )

抽象操作 SetIntegrityLevel 用于固定一个对象自身属性集合。 这个抽象操作执行步骤如下:

  1. Assert: Type(O) is Object.
  2. Assert: level is either "sealed" or "frozen".
  3. Let status be ? O.[[PreventExtensions]]().
  4. If status is false, return false.
  5. Let keys be ? O.[[OwnPropertyKeys]]().
  6. If level is "sealed", then
    1. For each element k of keys, do
      1. Perform ? DefinePropertyOrThrow(O, k, PropertyDescriptor { [[Configurable]]: false }).
  7. Else level is "frozen",
    1. For each element k of keys, do
      1. Let currentDesc be ? O.[[GetOwnProperty]](k).
      2. If currentDesc is not undefined, then
        1. If IsAccessorDescriptor(currentDesc) is true, then
          1. Let desc be the PropertyDescriptor { [[Configurable]]: false }.
        2. Else,
          1. Let desc be the PropertyDescriptor { [[Configurable]]: false, [[Writable]]: false }.
        3. Perform ? DefinePropertyOrThrow(O, k, desc).
  8. Return true.

7.3.15 TestIntegrityLevel ( O, level )

抽象操作 TestIntegrityLevel 用于检查对象自身属性是否被固定。这个抽象操作执行步骤如下:

  1. Assert: Type(O) is Object.
  2. Assert: level is either "sealed" or "frozen".
  3. Let status be ? IsExtensible(O).
  4. If status is true, return false.
  5. NOTE: If the object is extensible, none of its properties are examined.
  6. Let keys be ? O.[[OwnPropertyKeys]]().
  7. For each element k of keys, do
    1. Let currentDesc be ? O.[[GetOwnProperty]](k).
    2. If currentDesc is not undefined, then
      1. If currentDesc.[[Configurable]] is true, return false.
      2. If level is "frozen" and IsDataDescriptor(currentDesc) is true, then
        1. If currentDesc.[[Writable]] is true, return false.
  8. Return true.

7.3.16 CreateArrayFromList ( elements )

抽象操作 CreateArrayFromList 用于创建一个数组对象,其元素由由一个 List 的参数提供。该抽象操作执行以下步骤:

  1. Assert: elements is a List whose elements are all ECMAScript language values.
  2. Let array be ! ArrayCreate(0).
  3. Let n be 0.
  4. For each element e of elements, do
    1. Let status be CreateDataProperty(array, ! ToString(n), e).
    2. Assert: status is true.
    3. Increment n by 1.
  5. Return array.

7.3.17 CreateListFromArrayLike ( obj [ , elementTypes ] )

抽象操作 CreateListFromArrayLike 用于创建一个 List 值,其元素通过类数组对象 obj 属性的索引提供。可选参数 elementTypes 是一个包含 ECMAScript 语言类型的名称列表,表示被创建的 List 元素值被允许的类型。该抽象操作的执行步骤如下:

  1. If elementTypes is not present, set elementTypes to « Undefined, Null, Boolean, String, Symbol, Number, Object ».
  2. If Type(obj) is not Object, throw a TypeError exception.
  3. Let len be ? ToLength(? Get(obj, "length")).
  4. Let list be a new empty List.
  5. Let index be 0.
  6. Repeat, while index < len
    1. Let indexName be ! ToString(index).
    2. Let next be ? Get(obj, indexName).
    3. If Type(next) is not an element of elementTypes, throw a TypeError exception.
    4. Append next as the last element of list.
    5. Set index to index + 1.
  7. Return list.

7.3.18 Invoke ( V, P [ , argumentsList ] )

抽象操作 Invoke 用于调用一个 ECMAScript 语言值的方法属性。该操作用参数 以及可选参数 argumentsList 调用,其中 V 即作为属性的查找点也作为调用的 this 值, P 是属性 key, argumentsList 是传递给方法的参数列表。 如果 argumentsList 未提供,则使用一个空的 List 作为他的值。该抽象操作执行步骤如下:

  1. Assert: IsPropertyKey(P) is true.
  2. If argumentsList is not present, set argumentsList to a new empty List.
  3. Let func be ? GetV(V, P).
  4. Return ? Call(func, V, argumentsList).

7.3.19 OrdinaryHasInstance ( C, O )

抽象操作 OrdinaryHasInstance 执行默认算法,确定对象 O 是否继承自构找函数 C 提供的实例对象继承路劲。该抽象操作执行步骤如下:

  1. If IsCallable(C) is false, return false.
  2. If C has a [[BoundTargetFunction]] internal slot, then
    1. Let BC be C.[[BoundTargetFunction]].
    2. Return ? InstanceofOperator(O, BC).
  3. If Type(O) is not Object, return false.
  4. Let P be ? Get(C, "prototype").
  5. If Type(P) is not Object, throw a TypeError exception.
  6. Repeat,
    1. Set O to ? O.[[GetPrototypeOf]]().
    2. If O is null, return false.
    3. If SameValue(P, O) is true, return true.

7.3.20 SpeciesConstructor ( O, defaultConstructor )

抽象操作 SpeciesConstructor 用于检索用于创建新对象的构找函数,该新对象是从参数对象 O 派生的。如果在对象 O 属性中不能找到一个 constructor@@species 属性,则使用 defaultConstructor 作为构造函数。该抽象操作的执行步骤如下:

  1. Assert: Type(O) is Object.
  2. Let C be ? Get(O, "constructor").
  3. If C is undefined, return defaultConstructor.
  4. If Type(C) is not Object, throw a TypeError exception.
  5. Let S be ? Get(C, @@species).
  6. If S is either undefined or null, return defaultConstructor.
  7. If IsConstructor(S) is true, return S.
  8. Throw a TypeError exception.

7.3.21 EnumerableOwnPropertyNames ( O, kind )

当使用对象 O 和字符串 kind 作为参数调用抽象操作 EnumerableOwnPropertyNames 时执行以下步骤:

  1. Assert: Type(O) is Object.
  2. Let ownKeys be ? O.[[OwnPropertyKeys]]().
  3. Let properties be a new empty List.
  4. For each element key of ownKeys in List order, do
    1. If Type(key) is String, then
      1. Let desc be ? O.[[GetOwnProperty]](key).
      2. If desc is not undefined and desc.[[Enumerable]] is true, then
        1. If kind is "key", append key to properties.
        2. Else,
          1. Let value be ? Get(O, key).
          2. If kind is "value", append value to properties.
          3. Else,
            1. Assert: kind is "key+value".
            2. Let entry be CreateArrayFromListkey, value »).
            3. Append entry to properties.
  5. Order the elements of properties so they are in the same relative order as would be produced by the Iterator that would be returned if the EnumerateObjectProperties internal method were invoked with O.
  6. Return properties.

7.3.22 GetFunctionRealm ( obj )

参数为 obj抽象操作 GetFunctionRealm 执行以下步骤:

  1. Assert: obj is a callable object.
  2. If obj has a [[Realm]] internal slot, then
    1. Return obj.[[Realm]].
  3. If obj is a Bound Function exotic object, then
    1. Let target be obj.[[BoundTargetFunction]].
    2. Return ? GetFunctionRealm(target).
  4. If obj is a Proxy exotic object, then
    1. If obj.[[ProxyHandler]] is null, throw a TypeError exception.
    2. Let proxyTarget be obj.[[ProxyTarget]].
    3. Return ? GetFunctionRealm(proxyTarget).
  5. Return the current Realm Record.
Note

第五步只有在 obj 是一个没有 [[Realm]] 内部槽的非标准函数怪异对象时执行。

7.3.23 CopyDataProperties ( target, source, excludedItems )

When the abstract operation CopyDataProperties is called with arguments target, source, and excludedItems, the following steps are taken:

  1. Assert: Type(target) is Object.
  2. Assert: excludedItems is a List of property keys.
  3. If source is undefined or null, return target.
  4. Let from be ! ToObject(source).
  5. Let keys be ? from.[[OwnPropertyKeys]]().
  6. For each element nextKey of keys in List order, do
    1. Let excluded be false.
    2. For each element e of excludedItems in List order, do
      1. If SameValue(e, nextKey) is true, then
        1. Set excluded to true.
    3. If excluded is false, then
      1. Let desc be ? from.[[GetOwnProperty]](nextKey).
      2. If desc is not undefined and desc.[[Enumerable]] is true, then
        1. Let propValue be ? Get(from, nextKey).
        2. Perform ! CreateDataProperty(target, nextKey, propValue).
  7. Return target.
Note

The target passed in here is always a newly created object which is not directly accessible in case of an error being thrown.

7.4 迭代器对象具有的操作

参考常见的迭代接口 (25.1).

7.4.1 GetIterator ( obj [ , hint [, method ] )

参数为 obj 和可选参数 hint, method抽象操作 GetIterator 执行以下步骤:

  1. If hint is not present, set hint to sync.
  2. Assert: hint is either sync or async.
  3. If method is not present, then
    1. If hint is async, then
      1. Set method to ? GetMethod(obj, @@asyncIterator).
      2. If method is undefined, then
        1. Let syncMethod be ? GetMethod(obj, @@iterator).
        2. Let syncIteratorRecord be ? GetIterator(obj, sync, syncMethod).
        3. Return ? CreateAsyncFromSyncIterator(syncIteratorRecord).
    2. Otherwise, set method to ? GetMethod(obj, @@iterator).
  4. Let iterator be ? Call(method, obj).
  5. If Type(iterator) is not Object, throw a TypeError exception.
  6. Let nextMethod be ? GetV(iterator, "next").
  7. Let iteratorRecord be Record { [[Iterator]]: iterator, [[NextMethod]]: nextMethod, [[Done]]: false }.
  8. Return iteratorRecord.

7.4.2 IteratorNext ( iteratorRecord [ , value ] )

参数为 iteratorRecord 和可选参数 value抽象操作 IteratorNext 执行以下步骤:

  1. If value is not present, then
    1. Let result be ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]], « »).
  2. Else,
    1. Let result be ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]], « value »).
  3. If Type(result) is not Object, throw a TypeError exception.
  4. Return result.

7.4.3 IteratorComplete ( iterResult )

参数为 iterResult抽象操作 IteratorComplete 执行以下步骤:

  1. Assert: Type(iterResult) is Object.
  2. Return ToBoolean(? Get(iterResult, "done")).

7.4.4 IteratorValue ( iterResult )

使用参数为 iterResult抽象操作 IteratorValue 执行以下步骤:

  1. Assert: Type(iterResult) is Object.
  2. Return ? Get(iterResult, "value").

7.4.5 IteratorStep ( iteratorRecord )

使用参数 iteratorRecord抽象操作 IteratorStep 通过调用 iteratorRecord.[[NextMethod]] 从 iteratorRecord.[[Iterator]] 中请求 next 值,并返回 false 或一个 IteratorResult 对象。false 表示迭代结束,IteratorResult 对象是一个可用的 next 值。其执行步骤如下:

  1. Let result be ? IteratorNext(iteratorRecord).
  2. Let done be ? IteratorComplete(result).
  3. If done is true, return false.
  4. Return result.

7.4.6 IteratorClose ( iteratorRecord, completion )

参数为 iteratorRecordcompletion抽象操作 IteratorClose 用于通知迭代器,它应该执行它在达到其完成状态时通常会执行的一些操作:

  1. Assert: Type(iteratorRecord.[[Iterator]]) is Object.
  2. Assert: completion is a Completion Record.
  3. Let iterator be iteratorRecord.[[Iterator]].
  4. Let return be ? GetMethod(iterator, "return").
  5. If return is undefined, return Completion(completion).
  6. Let innerResult be Call(return, iterator, « »).
  7. If completion.[[Type]] is throw, return Completion(completion).
  8. If innerResult.[[Type]] is throw, return Completion(innerResult).
  9. If Type(innerResult.[[Value]]) is not Object, throw a TypeError exception.
  10. Return Completion(completion).

7.4.7 AsyncIteratorClose ( iteratorRecord, completion )

The abstract operation AsyncIteratorClose with arguments iteratorRecord and completion is used to notify an async iterator that it should perform any actions it would normally perform when it has reached its completed state:

  1. Assert: Type(iteratorRecord.[[Iterator]]) is Object.
  2. Assert: completion is a Completion Record.
  3. Let iterator be iteratorRecord.[[Iterator]].
  4. Let return be ? GetMethod(iterator, "return").
  5. If return is undefined, return Completion(completion).
  6. Let innerResult be Call(return, iterator, « »).
  7. If innerResult.[[Type]] is normal, set innerResult to Await(innerResult.[[Value]]).
  8. If completion.[[Type]] is throw, return Completion(completion).
  9. If innerResult.[[Type]] is throw, return Completion(innerResult).
  10. If Type(innerResult.[[Value]]) is not Object, throw a TypeError exception.
  11. Return Completion(completion).

7.4.8 CreateIterResultObject ( value, done )

参数为 valuedone抽象操作 CreateIterResultObject 创建一个支持 IteratorResult 接口的对象,它执行以下操作:

  1. Assert: Type(done) is Boolean.
  2. Let obj be ObjectCreate(%ObjectPrototype%).
  3. Perform CreateDataProperty(obj, "value", value).
  4. Perform CreateDataProperty(obj, "done", done).
  5. Return obj.

7.4.9 CreateListIteratorRecord ( list )

参数为 list抽象操作 CreateListIteratorRecord 创建一个迭代器 (25.1.1.2) 对象记录,其 next 方法返回元素连续的 list。该抽象操作执行以下步骤:

  1. Let iterator be ObjectCreate(%IteratorPrototype%, « [[IteratedList]], [[ListIteratorNextIndex]] »).
  2. Set iterator.[[IteratedList]] to list.
  3. Set iterator.[[ListIteratorNextIndex]] to 0.
  4. Let steps be the algorithm steps defined in ListIterator next (7.4.9.1).
  5. Let next be CreateBuiltinFunction(steps, « »).
  6. Return Record { [[Iterator]]: iterator, [[NextMethod]]: next, [[Done]]: false }.
Note

这个迭代器对象列表从不直接通过 ECMAScript 代码访问。

7.4.9.1 ListIterator next ( )

ListIterator next 方法是一个标准的内置函数方法(章节 17),它执行以下步骤:

  1. Let O be the this value.
  2. Assert: Type(O) is Object.
  3. Assert: O has an [[IteratedList]] internal slot.
  4. Let list be O.[[IteratedList]].
  5. Let index be O.[[ListIteratorNextIndex]].
  6. Let len be the number of elements of list.
  7. If indexlen, then
    1. Return CreateIterResultObject(undefined, true).
  8. Set O.[[ListIteratorNextIndex]] to index+1.
  9. Return CreateIterResultObject(list[index], false).

8 Executable Code and Execution Contexts

8.1 Lexical Environments

A Lexical Environment is a specification type used to define the association of Identifiers to specific variables and functions based upon the lexical nesting structure of ECMAScript code. A Lexical Environment consists of an Environment Record and a possibly null reference to an outer Lexical Environment. Usually a Lexical Environment is associated with some specific syntactic structure of ECMAScript code such as a FunctionDeclaration, a BlockStatement, or a Catch clause of a TryStatement and a new Lexical Environment is created each time such code is evaluated.

An Environment Record records the identifier bindings that are created within the scope of its associated Lexical Environment. It is referred to as the Lexical Environment's EnvironmentRecord.

The outer environment reference is used to model the logical nesting of Lexical Environment values. The outer reference of a (inner) Lexical Environment is a reference to the Lexical Environment that logically surrounds the inner Lexical Environment. An outer Lexical Environment may, of course, have its own outer Lexical Environment. A Lexical Environment may serve as the outer environment for multiple inner Lexical Environments. For example, if a FunctionDeclaration contains two nested FunctionDeclarations then the Lexical Environments of each of the nested functions will have as their outer Lexical Environment the Lexical Environment of the current evaluation of the surrounding function.

A global environment is a Lexical Environment which does not have an outer environment. The global environment's outer environment reference is null. A global environment's EnvironmentRecord may be prepopulated with identifier bindings and includes an associated global object whose properties provide some of the global environment's identifier bindings. As ECMAScript code is executed, additional properties may be added to the global object and the initial properties may be modified.

A module environment is a Lexical Environment that contains the bindings for the top level declarations of a Module. It also contains the bindings that are explicitly imported by the Module. The outer environment of a module environment is a global environment.

A function environment is a Lexical Environment that corresponds to the invocation of an ECMAScript function object. A function environment may establish a new this binding. A function environment also captures the state necessary to support super method invocations.

Lexical Environments and Environment Record values are purely specification mechanisms and need not correspond to any specific artefact of an ECMAScript implementation. It is impossible for an ECMAScript program to directly access or manipulate such values.

8.1.1 Environment Records

There are two primary kinds of Environment Record values used in this specification: declarative Environment Records and object Environment Records. Declarative Environment Records are used to define the effect of ECMAScript language syntactic elements such as FunctionDeclarations, VariableDeclarations, and Catch clauses that directly associate identifier bindings with ECMAScript language values. Object Environment Records are used to define the effect of ECMAScript elements such as WithStatement that associate identifier bindings with the properties of some object. Global Environment Records and function Environment Records are specializations that are used for specifically for Script global declarations and for top-level declarations within functions.

For specification purposes Environment Record values are values of the Record specification type and can be thought of as existing in a simple object-oriented hierarchy where Environment Record is an abstract class with three concrete subclasses, declarative Environment Record, object Environment Record, and global Environment Record. Function Environment Records and module Environment Records are subclasses of declarative Environment Record. The abstract class includes the abstract specification methods defined in Table 14. These abstract methods have distinct concrete algorithms for each of the concrete subclasses.

Table 14: Abstract Methods of Environment Records
Method Purpose
HasBinding(N) Determine if an Environment Record has a binding for the String value N. Return true if it does and false if it does not.
CreateMutableBinding(N, D) Create a new but uninitialized mutable binding in an Environment Record. The String value N is the text of the bound name. If the Boolean argument D is true the binding may be subsequently deleted.
CreateImmutableBinding(N, S) Create a new but uninitialized immutable binding in an Environment Record. The String value N is the text of the bound name. If S is true then attempts to set it after it has been initialized will always throw an exception, regardless of the strict mode setting of operations that reference that binding.
InitializeBinding(N, V) Set the value of an already existing but uninitialized binding in an Environment Record. The String value N is the text of the bound name. V is the value for the binding and is a value of any ECMAScript language type.
SetMutableBinding(N, V, S) Set the value of an already existing mutable binding in an Environment Record. The String value N is the text of the bound name. V is the value for the binding and may be a value of any ECMAScript language type. S is a Boolean flag. If S is true and the binding cannot be set throw a TypeError exception.
GetBindingValue(N, S) Returns the value of an already existing binding from an Environment Record. The String value N is the text of the bound name. S is used to identify references originating in strict mode code or that otherwise require strict mode reference semantics. If S is true and the binding does not exist throw a ReferenceError exception. If the binding exists but is uninitialized a ReferenceError is thrown, regardless of the value of S.
DeleteBinding(N) Delete a binding from an Environment Record. The String value N is the text of the bound name. If a binding for N exists, remove the binding and return true. If the binding exists but cannot be removed return false. If the binding does not exist return true.
HasThisBinding() Determine if an Environment Record establishes a this binding. Return true if it does and false if it does not.
HasSuperBinding() Determine if an Environment Record establishes a super method binding. Return true if it does and false if it does not.
WithBaseObject() If this Environment Record is associated with a with statement, return the with object. Otherwise, return undefined.

8.1.1.1 Declarative Environment Records

Each declarative Environment Record is associated with an ECMAScript program scope containing variable, constant, let, class, module, import, and/or function declarations. A declarative Environment Record binds the set of identifiers defined by the declarations contained within its scope.

The behaviour of the concrete specification methods for declarative Environment Records is defined by the following algorithms.

8.1.1.1.1 HasBinding ( N )

The concrete Environment Record method HasBinding for declarative Environment Records simply determines if the argument identifier is one of the identifiers bound by the record:

  1. Let envRec be the declarative Environment Record for which the method was invoked.
  2. If envRec has a binding for the name that is the value of N, return true.
  3. Return false.

8.1.1.1.2 CreateMutableBinding ( N, D )

The concrete Environment Record method CreateMutableBinding for declarative Environment Records creates a new mutable binding for the name N that is uninitialized. A binding must not already exist in this Environment Record for N. If Boolean argument D has the value true the new binding is marked as being subject to deletion.

  1. Let envRec be the declarative Environment Record for which the method was invoked.
  2. Assert: envRec does not already have a binding for N.
  3. Create a mutable binding in envRec for N and record that it is uninitialized. If D is true, record that the newly created binding may be deleted by a subsequent DeleteBinding call.
  4. Return NormalCompletion(empty).

8.1.1.1.3 CreateImmutableBinding ( N, S )

The concrete Environment Record method CreateImmutableBinding for declarative Environment Records creates a new immutable binding for the name N that is uninitialized. A binding must not already exist in this Environment Record for N. If the Boolean argument S has the value true the new binding is marked as a strict binding.

  1. Let envRec be the declarative Environment Record for which the method was invoked.
  2. Assert: envRec does not already have a binding for N.
  3. Create an immutable binding in envRec for N and record that it is uninitialized. If S is true, record that the newly created binding is a strict binding.
  4. Return NormalCompletion(empty).

8.1.1.1.4 InitializeBinding ( N, V )

The concrete Environment Record method InitializeBinding for declarative Environment Records is used to set the bound value of the current binding of the identifier whose name is the value of the argument N to the value of argument V. An uninitialized binding for N must already exist.

  1. Let envRec be the declarative Environment Record for which the method was invoked.
  2. Assert: envRec must have an uninitialized binding for N.
  3. Set the bound value for N in envRec to V.
  4. Record that the binding for N in envRec has been initialized.
  5. Return NormalCompletion(empty).

8.1.1.1.5 SetMutableBinding ( N, V, S )

The concrete Environment Record method SetMutableBinding for declarative Environment Records attempts to change the bound value of the current binding of the identifier whose name is the value of the argument N to the value of argument V. A binding for N normally already exists, but in rare cases it may not. If the binding is an immutable binding, a TypeError is thrown if S is true.

  1. Let envRec be the declarative Environment Record for which the method was invoked.
  2. If envRec does not have a binding for N, then
    1. If S is true, throw a ReferenceError exception.
    2. Perform envRec.CreateMutableBinding(N, true).
    3. Perform envRec.InitializeBinding(N, V).
    4. Return NormalCompletion(empty).
  3. If the binding for N in envRec is a strict binding, set S to true.
  4. If the binding for N in envRec has not yet been initialized, throw a ReferenceError exception.
  5. Else if the binding for N in envRec is a mutable binding, change its bound value to V.
  6. Else,
    1. Assert: This is an attempt to change the value of an immutable binding.
    2. If S is true, throw a TypeError exception.
  7. Return NormalCompletion(empty).
Note

An example of ECMAScript code that results in a missing binding at step 2 is:

function f(){eval("var x; x = (delete x, 0);")}

8.1.1.1.6 GetBindingValue ( N, S )

The concrete Environment Record method GetBindingValue for declarative Environment Records simply returns the value of its bound identifier whose name is the value of the argument N. If the binding exists but is uninitialized a ReferenceError is thrown, regardless of the value of S.

  1. Let envRec be the declarative Environment Record for which the method was invoked.
  2. Assert: envRec has a binding for N.
  3. If the binding for N in envRec is an uninitialized binding, throw a ReferenceError exception.
  4. Return the value currently bound to N in envRec.

8.1.1.1.7 DeleteBinding ( N )

The concrete Environment Record method DeleteBinding for declarative Environment Records can only delete bindings that have been explicitly designated as being subject to deletion.

  1. Let envRec be the declarative Environment Record for which the method was invoked.
  2. Assert: envRec has a binding for the name that is the value of N.
  3. If the binding for N in envRec cannot be deleted, return false.
  4. Remove the binding for N from envRec.
  5. Return true.

8.1.1.1.8 HasThisBinding ( )

Regular declarative Environment Records do not provide a this binding.

  1. Return false.

8.1.1.1.9 HasSuperBinding ( )

Regular declarative Environment Records do not provide a super binding.

  1. Return false.

8.1.1.1.10 WithBaseObject ( )

Declarative Environment Records always return undefined as their WithBaseObject.

  1. Return undefined.

8.1.1.2 Object Environment Records

Each object Environment Record is associated with an object called its binding object. An object Environment Record binds the set of string identifier names that directly correspond to the property names of its binding object. Property keys that are not strings in the form of an IdentifierName are not included in the set of bound identifiers. Both own and inherited properties are included in the set regardless of the setting of their [[Enumerable]] attribute. Because properties can be dynamically added and deleted from objects, the set of identifiers bound by an object Environment Record may potentially change as a side-effect of any operation that adds or deletes properties. Any bindings that are created as a result of such a side-effect are considered to be a mutable binding even if the Writable attribute of the corresponding property has the value false. Immutable bindings do not exist for object Environment Records.

Object Environment Records created for with statements (13.11) can provide their binding object as an implicit this value for use in function calls. The capability is controlled by a withEnvironment Boolean value that is associated with each object Environment Record. By default, the value of withEnvironment is false for any object Environment Record.

The behaviour of the concrete specification methods for object Environment Records is defined by the following algorithms.

8.1.1.2.1 HasBinding ( N )

The concrete Environment Record method HasBinding for object Environment Records determines if its associated binding object has a property whose name is the value of the argument N:

  1. Let envRec be the object Environment Record for which the method was invoked.
  2. Let bindings be the binding object for envRec.
  3. Let foundBinding be ? HasProperty(bindings, N).
  4. If foundBinding is false, return false.
  5. If the withEnvironment flag of envRec is false, return true.
  6. Let unscopables be ? Get(bindings, @@unscopables).
  7. If Type(unscopables) is Object, then
    1. Let blocked be ToBoolean(? Get(unscopables, N)).
    2. If blocked is true, return false.
  8. Return true.

8.1.1.2.2 CreateMutableBinding ( N, D )

The concrete Environment Record method CreateMutableBinding for object Environment Records creates in an Environment Record's associated binding object a property whose name is the String value and initializes it to the value undefined. If Boolean argument D has the value true the new property's [[Configurable]] attribute is set to true; otherwise it is set to false.

  1. Let envRec be the object Environment Record for which the method was invoked.
  2. Let bindings be the binding object for envRec.
  3. Return ? DefinePropertyOrThrow(bindings, N, PropertyDescriptor { [[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: D }).
Note

Normally envRec will not have a binding for N but if it does, the semantics of DefinePropertyOrThrow may result in an existing binding being replaced or shadowed or cause an abrupt completion to be returned.

8.1.1.2.3 CreateImmutableBinding ( N, S )

The concrete Environment Record method CreateImmutableBinding is never used within this specification in association with object Environment Records.

8.1.1.2.4 InitializeBinding ( N, V )

The concrete Environment Record method InitializeBinding for object Environment Records is used to set the bound value of the current binding of the identifier whose name is the value of the argument N to the value of argument V. An uninitialized binding for N must already exist.

  1. Let envRec be the object Environment Record for which the method was invoked.
  2. Assert: envRec must have an uninitialized binding for N.
  3. Record that the binding for N in envRec has been initialized.
  4. Return ? envRec.SetMutableBinding(N, V, false).
Note

In this specification, all uses of CreateMutableBinding for object Environment Records are immediately followed by a call to InitializeBinding for the same name. Hence, implementations do not need to explicitly track the initialization state of individual object Environment Record bindings.

8.1.1.2.5 SetMutableBinding ( N, V, S )

The concrete Environment Record method SetMutableBinding for object Environment Records attempts to set the value of the Environment Record's associated binding object's property whose name is the value of the argument N to the value of argument V. A property named N normally already exists but if it does not or is not currently writable, error handling is determined by the value of the Boolean argument S.

  1. Let envRec be the object Environment Record for which the method was invoked.
  2. Let bindings be the binding object for envRec.
  3. Return ? Set(bindings, N, V, S).

8.1.1.2.6 GetBindingValue ( N, S )

The concrete Environment Record method GetBindingValue for object Environment Records returns the value of its associated binding object's property whose name is the String value of the argument identifier N. The property should already exist but if it does not the result depends upon the value of the S argument:

  1. Let envRec be the object Environment Record for which the method was invoked.
  2. Let bindings be the binding object for envRec.
  3. Let value be ? HasProperty(bindings, N).
  4. If value is false, then
    1. If S is false, return the value undefined; otherwise throw a ReferenceError exception.
  5. Return ? Get(bindings, N).

8.1.1.2.7 DeleteBinding ( N )

The concrete Environment Record method DeleteBinding for object Environment Records can only delete bindings that correspond to properties of the environment object whose [[Configurable]] attribute have the value true.

  1. Let envRec be the object Environment Record for which the method was invoked.
  2. Let bindings be the binding object for envRec.
  3. Return ? bindings.[[Delete]](N).

8.1.1.2.8 HasThisBinding ( )

Regular object Environment Records do not provide a this binding.

  1. Return false.

8.1.1.2.9 HasSuperBinding ( )

Regular object Environment Records do not provide a super binding.

  1. Return false.

8.1.1.2.10 WithBaseObject ( )

Object Environment Records return undefined as their WithBaseObject unless their withEnvironment flag is true.

  1. Let envRec be the object Environment Record for which the method was invoked.
  2. If the withEnvironment flag of envRec is true, return the binding object for envRec.
  3. Otherwise, return undefined.

8.1.1.3 Function Environment Records

A function Environment Record is a declarative Environment Record that is used to represent the top-level scope of a function and, if the function is not an ArrowFunction, provides a this binding. If a function is not an ArrowFunction function and references super, its function Environment Record also contains the state that is used to perform super method invocations from within the function.

Function Environment Records have the additional state fields listed in Table 15.

Table 15: Additional Fields of Function Environment Records
Field Name Value Meaning
[[ThisValue]] Any This is the this value used for this invocation of the function.
[[ThisBindingStatus]] "lexical" | "initialized" | "uninitialized" If the value is "lexical", this is an ArrowFunction and does not have a local this value.
[[FunctionObject]] Object The function object whose invocation caused this Environment Record to be created.
[[HomeObject]] Object | undefined If the associated function has super property accesses and is not an ArrowFunction, [[HomeObject]] is the object that the function is bound to as a method. The default value for [[HomeObject]] is undefined.
[[NewTarget]] Object | undefined If this Environment Record was created by the [[Construct]] internal method, [[NewTarget]] is the value of the [[Construct]] newTarget parameter. Otherwise, its value is undefined.

Function Environment Records support all of the declarative Environment Record methods listed in Table 14 and share the same specifications for all of those methods except for HasThisBinding and HasSuperBinding. In addition, function Environment Records support the methods listed in Table 16:

Table 16: Additional Methods of Function Environment Records
Method Purpose
BindThisValue(V) Set the [[ThisValue]] and record that it has been initialized.
GetThisBinding() Return the value of this Environment Record's this binding. Throws a ReferenceError if the this binding has not been initialized.
GetSuperBase() Return the object that is the base for super property accesses bound in this Environment Record. The object is derived from this Environment Record's [[HomeObject]] field. The value undefined indicates that super property accesses will produce runtime errors.

The behaviour of the additional concrete specification methods for function Environment Records is defined by the following algorithms:

8.1.1.3.1 BindThisValue ( V )

  1. Let envRec be the function Environment Record for which the method was invoked.
  2. Assert: envRec.[[ThisBindingStatus]] is not "lexical".
  3. If envRec.[[ThisBindingStatus]] is "initialized", throw a ReferenceError exception.
  4. Set envRec.[[ThisValue]] to V.
  5. Set envRec.[[ThisBindingStatus]] to "initialized".
  6. Return V.

8.1.1.3.2 HasThisBinding ( )

  1. Let envRec be the function Environment Record for which the method was invoked.
  2. If envRec.[[ThisBindingStatus]] is "lexical", return false; otherwise, return true.

8.1.1.3.3 HasSuperBinding ( )

  1. Let envRec be the function Environment Record for which the method was invoked.
  2. If envRec.[[ThisBindingStatus]] is "lexical", return false.
  3. If envRec.[[HomeObject]] has the value undefined, return false; otherwise, return true.

8.1.1.3.4 GetThisBinding ( )

  1. Let envRec be the function Environment Record for which the method was invoked.
  2. Assert: envRec.[[ThisBindingStatus]] is not "lexical".
  3. If envRec.[[ThisBindingStatus]] is "uninitialized", throw a ReferenceError exception.
  4. Return envRec.[[ThisValue]].

8.1.1.3.5 GetSuperBase ( )

  1. Let envRec be the function Environment Record for which the method was invoked.
  2. Let home be envRec.[[HomeObject]].
  3. If home has the value undefined, return undefined.
  4. Assert: Type(home) is Object.
  5. Return ? home.[[GetPrototypeOf]]().

8.1.1.4 Global Environment Records

A global Environment Record is used to represent the outer most scope that is shared by all of the ECMAScript Script elements that are processed in a common realm. A global Environment Record provides the bindings for built-in globals (clause 18), properties of the global object, and for all top-level declarations (13.2.8, 13.2.10) that occur within a Script.

A global Environment Record is logically a single record but it is specified as a composite encapsulating an object Environment Record and a declarative Environment Record. The object Environment Record has as its base object the global object of the associated Realm Record. This global object is the value returned by the global Environment Record's GetThisBinding concrete method. The object Environment Record component of a global Environment Record contains the bindings for all built-in globals (clause 18) and all bindings introduced by a FunctionDeclaration, GeneratorDeclaration, AsyncFunctionDeclaration, AsyncGeneratorDeclaration, or VariableStatement contained in global code. The bindings for all other ECMAScript declarations in global code are contained in the declarative Environment Record component of the global Environment Record.

Properties may be created directly on a global object. Hence, the object Environment Record component of a global Environment Record may contain both bindings created explicitly by FunctionDeclaration, GeneratorDeclaration, AsyncFunctionDeclaration, AsyncGeneratorDeclaration, or VariableDeclaration declarations and bindings created implicitly as properties of the global object. In order to identify which bindings were explicitly created using declarations, a global Environment Record maintains a list of the names bound using its CreateGlobalVarBinding and CreateGlobalFunctionBinding concrete methods.

Global Environment Records have the additional fields listed in Table 17 and the additional methods listed in Table 18.

Table 17: Additional Fields of Global Environment Records
Field Name Value Meaning
[[ObjectRecord]] Object Environment Record Binding object is the global object. It contains global built-in bindings as well as FunctionDeclaration, GeneratorDeclaration, AsyncFunctionDeclaration, AsyncGeneratorDeclaration, and VariableDeclaration bindings in global code for the associated realm.
[[GlobalThisValue]] Object The value returned by this in global scope. Hosts may provide any ECMAScript Object value.
[[DeclarativeRecord]] Declarative Environment Record Contains bindings for all declarations in global code for the associated realm code except for FunctionDeclaration, GeneratorDeclaration, AsyncFunctionDeclaration, AsyncGeneratorDeclaration, and VariableDeclaration bindings.
[[VarNames]] List of String The string names bound by FunctionDeclaration, GeneratorDeclaration, AsyncFunctionDeclaration, AsyncGeneratorDeclaration, and VariableDeclaration declarations in global code for the associated realm.
Table 18: Additional Methods of Global Environment Records
Method Purpose
GetThisBinding() Return the value of this Environment Record's this binding.
HasVarDeclaration (N) Determines if the argument identifier has a binding in this Environment Record that was created using a VariableDeclaration, FunctionDeclaration, GeneratorDeclaration, AsyncFunctionDeclaration, or AsyncGeneratorDeclaration.
HasLexicalDeclaration (N) Determines if the argument identifier has a binding in this Environment Record that was created using a lexical declaration such as a LexicalDeclaration or a ClassDeclaration.
HasRestrictedGlobalProperty (N) Determines if the argument is the name of a global object property that may not be shadowed by a global lexical binding.
CanDeclareGlobalVar (N) Determines if a corresponding CreateGlobalVarBinding call would succeed if called for the same argument N.
CanDeclareGlobalFunction (N) Determines if a corresponding CreateGlobalFunctionBinding call would succeed if called for the same argument N.
CreateGlobalVarBinding(N, D) Used to create and initialize to undefined a global var binding in the [[ObjectRecord]] component of a global Environment Record. The binding will be a mutable binding. The corresponding global object property will have attribute values appropriate for a var. The String value N is the bound name. If D is true the binding may be deleted. Logically equivalent to CreateMutableBinding followed by a SetMutableBinding but it allows var declarations to receive special treatment.
CreateGlobalFunctionBinding(N, V, D) Create and initialize a global function binding in the [[ObjectRecord]] component of a global Environment Record. The binding will be a mutable binding. The corresponding global object property will have attribute values appropriate for a function. The String value N is the bound name. V is the initialization value. If the Boolean argument D is true the binding may be deleted. Logically equivalent to CreateMutableBinding followed by a SetMutableBinding but it allows function declarations to receive special treatment.

The behaviour of the concrete specification methods for global Environment Records is defined by the following algorithms.

8.1.1.4.1 HasBinding ( N )

The concrete Environment Record method HasBinding for global Environment Records simply determines if the argument identifier is one of the identifiers bound by the record:

  1. Let envRec be the global Environment Record for which the method was invoked.
  2. Let DclRec be envRec.[[DeclarativeRecord]].
  3. If DclRec.HasBinding(N) is true, return true.
  4. Let ObjRec be envRec.[[ObjectRecord]].
  5. Return ? ObjRec.HasBinding(N).

8.1.1.4.2 CreateMutableBinding ( N, D )

The concrete Environment Record method CreateMutableBinding for global Environment Records creates a new mutable binding for the name N that is uninitialized. The binding is created in the associated DeclarativeRecord. A binding for N must not already exist in the DeclarativeRecord. If Boolean argument D has the value true the new binding is marked as being subject to deletion.

  1. Let envRec be the global Environment Record for which the method was invoked.
  2. Let DclRec be envRec.[[DeclarativeRecord]].
  3. If DclRec.HasBinding(N) is true, throw a TypeError exception.
  4. Return DclRec.CreateMutableBinding(N, D).

8.1.1.4.3 CreateImmutableBinding ( N, S )

The concrete Environment Record method CreateImmutableBinding for global Environment Records creates a new immutable binding for the name N that is uninitialized. A binding must not already exist in this Environment Record for N. If the Boolean argument S has the value true the new binding is marked as a strict binding.

  1. Let envRec be the global Environment Record for which the method was invoked.
  2. Let DclRec be envRec.[[DeclarativeRecord]].
  3. If DclRec.HasBinding(N) is true, throw a TypeError exception.
  4. Return DclRec.CreateImmutableBinding(N, S).

8.1.1.4.4 InitializeBinding ( N, V )

The concrete Environment Record method InitializeBinding for global Environment Records is used to set the bound value of the current binding of the identifier whose name is the value of the argument N to the value of argument V. An uninitialized binding for N must already exist.

  1. Let envRec be the global Environment Record for which the method was invoked.
  2. Let DclRec be envRec.[[DeclarativeRecord]].
  3. If DclRec.HasBinding(N) is true, then
    1. Return DclRec.InitializeBinding(N, V).
  4. Assert: If the binding exists, it must be in the object Environment Record.
  5. Let ObjRec be envRec.[[ObjectRecord]].
  6. Return ? ObjRec.InitializeBinding(N, V).

8.1.1.4.5 SetMutableBinding ( N, V, S )

The concrete Environment Record method SetMutableBinding for global Environment Records attempts to change the bound value of the current binding of the identifier whose name is the value of the argument N to the value of argument V. If the binding is an immutable binding, a TypeError is thrown if S is true. A property named N normally already exists but if it does not or is not currently writable, error handling is determined by the value of the Boolean argument S.

  1. Let envRec be the global Environment Record for which the method was invoked.
  2. Let DclRec be envRec.[[DeclarativeRecord]].
  3. If DclRec.HasBinding(N) is true, then
    1. Return DclRec.SetMutableBinding(N, V, S).
  4. Let ObjRec be envRec.[[ObjectRecord]].
  5. Return ? ObjRec.SetMutableBinding(N, V, S).

8.1.1.4.6 GetBindingValue ( N, S )

The concrete Environment Record method GetBindingValue for global Environment Records returns the value of its bound identifier whose name is the value of the argument N. If the binding is an uninitialized binding throw a ReferenceError exception. A property named N normally already exists but if it does not or is not currently writable, error handling is determined by the value of the Boolean argument S.

  1. Let envRec be the global Environment Record for which the method was invoked.
  2. Let DclRec be envRec.[[DeclarativeRecord]].
  3. If DclRec.HasBinding(N) is true, then
    1. Return DclRec.GetBindingValue(N, S).
  4. Let ObjRec be envRec.[[ObjectRecord]].
  5. Return ? ObjRec.GetBindingValue(N, S).

8.1.1.4.7 DeleteBinding ( N )

The concrete Environment Record method DeleteBinding for global Environment Records can only delete bindings that have been explicitly designated as being subject to deletion.

  1. Let envRec be the global Environment Record for which the method was invoked.
  2. Let DclRec be envRec.[[DeclarativeRecord]].
  3. If DclRec.HasBinding(N) is true, then
    1. Return DclRec.DeleteBinding(N).
  4. Let ObjRec be envRec.[[ObjectRecord]].
  5. Let globalObject be the binding object for ObjRec.
  6. Let existingProp be ? HasOwnProperty(globalObject, N).
  7. If existingProp is true, then
    1. Let status be ? ObjRec.DeleteBinding(N).
    2. If status is true, then
      1. Let varNames be envRec.[[VarNames]].
      2. If N is an element of varNames, remove that element from the varNames.
    3. Return status.
  8. Return true.

8.1.1.4.8 HasThisBinding ( )

  1. Return true.

8.1.1.4.9 HasSuperBinding ( )

  1. Return false.

8.1.1.4.10 WithBaseObject ( )

Global Environment Records always return undefined as their WithBaseObject.

  1. Return undefined.

8.1.1.4.11 GetThisBinding ( )

  1. Let envRec be the global Environment Record for which the method was invoked.
  2. Return envRec.[[GlobalThisValue]].

8.1.1.4.12 HasVarDeclaration ( N )

The concrete Environment Record method HasVarDeclaration for global Environment Records determines if the argument identifier has a binding in this record that was created using a VariableStatement or a FunctionDeclaration:

  1. Let envRec be the global Environment Record for which the method was invoked.
  2. Let varDeclaredNames be envRec.[[VarNames]].
  3. If varDeclaredNames contains N, return true.
  4. Return false.

8.1.1.4.13 HasLexicalDeclaration ( N )

The concrete Environment Record method HasLexicalDeclaration for global Environment Records determines if the argument identifier has a binding in this record that was created using a lexical declaration such as a LexicalDeclaration or a ClassDeclaration:

  1. Let envRec be the global Environment Record for which the method was invoked.
  2. Let DclRec be envRec.[[DeclarativeRecord]].
  3. Return DclRec.HasBinding(N).

8.1.1.4.14 HasRestrictedGlobalProperty ( N )

The concrete Environment Record method HasRestrictedGlobalProperty for global Environment Records determines if the argument identifier is the name of a property of the global object that must not be shadowed by a global lexical binding:

  1. Let envRec be the global Environment Record for which the method was invoked.
  2. Let ObjRec be envRec.[[ObjectRecord]].
  3. Let globalObject be the binding object for ObjRec.
  4. Let existingProp be ? globalObject.[[GetOwnProperty]](N).
  5. If existingProp is undefined, return false.
  6. If existingProp.[[Configurable]] is true, return false.
  7. Return true.
Note

Properties may exist upon a global object that were directly created rather than being declared using a var or function declaration. A global lexical binding may not be created that has the same name as a non-configurable property of the global object. The global property undefined is an example of such a property.

8.1.1.4.15 CanDeclareGlobalVar ( N )

The concrete Environment Record method CanDeclareGlobalVar for global Environment Records determines if a corresponding CreateGlobalVarBinding call would succeed if called for the same argument N. Redundant var declarations and var declarations for pre-existing global object properties are allowed.

  1. Let envRec be the global Environment Record for which the method was invoked.
  2. Let ObjRec be envRec.[[ObjectRecord]].
  3. Let globalObject be the binding object for ObjRec.
  4. Let hasProperty be ? HasOwnProperty(globalObject, N).
  5. If hasProperty is true, return true.
  6. Return ? IsExtensible(globalObject).

8.1.1.4.16 CanDeclareGlobalFunction ( N )

The concrete Environment Record method CanDeclareGlobalFunction for global Environment Records determines if a corresponding CreateGlobalFunctionBinding call would succeed if called for the same argument N.

  1. Let envRec be the global Environment Record for which the method was invoked.
  2. Let ObjRec be envRec.[[ObjectRecord]].
  3. Let globalObject be the binding object for ObjRec.
  4. Let existingProp be ? globalObject.[[GetOwnProperty]](N).
  5. If existingProp is undefined, return ? IsExtensible(globalObject).
  6. If existingProp.[[Configurable]] is true, return true.
  7. If IsDataDescriptor(existingProp) is true and existingProp has attribute values { [[Writable]]: true, [[Enumerable]]: true }, return true.
  8. Return false.

8.1.1.4.17 CreateGlobalVarBinding ( N, D )

The concrete Environment Record method CreateGlobalVarBinding for global Environment Records creates and initializes a mutable binding in the associated object Environment Record and records the bound name in the associated [[VarNames]] List. If a binding already exists, it is reused and assumed to be initialized.

  1. Let envRec be the global Environment Record for which the method was invoked.
  2. Let ObjRec be envRec.[[ObjectRecord]].
  3. Let globalObject be the binding object for ObjRec.
  4. Let hasProperty be ? HasOwnProperty(globalObject, N).
  5. Let extensible be ? IsExtensible(globalObject).
  6. If hasProperty is false and extensible is true, then
    1. Perform ? ObjRec.CreateMutableBinding(N, D).
    2. Perform ? ObjRec.InitializeBinding(N, undefined).
  7. Let varDeclaredNames be envRec.[[VarNames]].
  8. If varDeclaredNames does not contain N, then
    1. Append N to varDeclaredNames.
  9. Return NormalCompletion(empty).

8.1.1.4.18 CreateGlobalFunctionBinding ( N, V, D )

The concrete Environment Record method CreateGlobalFunctionBinding for global Environment Records creates and initializes a mutable binding in the associated object Environment Record and records the bound name in the associated [[VarNames]] List. If a binding already exists, it is replaced.

  1. Let envRec be the global Environment Record for which the method was invoked.
  2. Let ObjRec be envRec.[[ObjectRecord]].
  3. Let globalObject be the binding object for ObjRec.
  4. Let existingProp be ? globalObject.[[GetOwnProperty]](N).
  5. If existingProp is undefined or existingProp.[[Configurable]] is true, then
    1. Let desc be the PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: D }.
  6. Else,
    1. Let desc be the PropertyDescriptor { [[Value]]: V }.
  7. Perform ? DefinePropertyOrThrow(globalObject, N, desc).
  8. Record that the binding for N in ObjRec has been initialized.
  9. Perform ? Set(globalObject, N, V, false).
  10. Let varDeclaredNames be envRec.[[VarNames]].
  11. If varDeclaredNames does not contain N, then
    1. Append N to varDeclaredNames.
  12. Return NormalCompletion(empty).
Note

Global function declarations are always represented as own properties of the global object. If possible, an existing own property is reconfigured to have a standard set of attribute values. Steps 8-9 are equivalent to what calling the InitializeBinding concrete method would do and if globalObject is a Proxy will produce the same sequence of Proxy trap calls.

8.1.1.5 Module Environment Records

A module Environment Record is a declarative Environment Record that is used to represent the outer scope of an ECMAScript Module. In additional to normal mutable and immutable bindings, module Environment Records also provide immutable import bindings which are bindings that provide indirect access to a target binding that exists in another Environment Record.

Module Environment Records support all of the declarative Environment Record methods listed in Table 14 and share the same specifications for all of those methods except for GetBindingValue, DeleteBinding, HasThisBinding and GetThisBinding. In addition, module Environment Records support the methods listed in Table 19:

Table 19: Additional Methods of Module Environment Records
Method Purpose
CreateImportBinding(N, M, N2) Create an immutable indirect binding in a module Environment Record. The String value N is the text of the bound name. M is a Module Record, and N2 is a binding that exists in M's module Environment Record.
GetThisBinding() Return the value of this Environment Record's this binding.

The behaviour of the additional concrete specification methods for module Environment Records are defined by the following algorithms:

8.1.1.5.1 GetBindingValue ( N, S )

The concrete Environment Record method GetBindingValue for module Environment Records returns the value of its bound identifier whose name is the value of the argument N. However, if the binding is an indirect binding the value of the target binding is returned. If the binding exists but is uninitialized a ReferenceError is thrown.

  1. Assert: S is true.
  2. Let envRec be the module Environment Record for which the method was invoked.
  3. Assert: envRec has a binding for N.
  4. If the binding for N is an indirect binding, then
    1. Let M and N2 be the indirection values provided when this binding for N was created.
    2. Let targetEnv be M.[[Environment]].
    3. If targetEnv is undefined, throw a ReferenceError exception.
    4. Let targetER be targetEnv's EnvironmentRecord.
    5. Return ? targetER.GetBindingValue(N2, true).
  5. If the binding for N in envRec is an uninitialized binding, throw a ReferenceError exception.
  6. Return the value currently bound to N in envRec.
Note

S will always be true because a Module is always strict mode code.

8.1.1.5.2 DeleteBinding ( N )

The concrete Environment Record method DeleteBinding for module Environment Records refuses to delete bindings.

  1. Assert: This method is never invoked. See 12.5.3.1.
Note

Module Environment Records are only used within strict code and an early error rule prevents the delete operator, in strict code, from being applied to a Reference that would resolve to a module Environment Record binding. See 12.5.3.1.

8.1.1.5.3 HasThisBinding ( )

Module Environment Records provide a this binding.

  1. Return true.

8.1.1.5.4 GetThisBinding ( )

  1. Return undefined.

8.1.1.5.5 CreateImportBinding ( N, M, N2 )

The concrete Environment Record method CreateImportBinding for module Environment Records creates a new initialized immutable indirect binding for the name N. A binding must not already exist in this Environment Record for N. M is a Module Record, and N2 is the name of a binding that exists in M's module Environment Record. Accesses to the value of the new binding will indirectly access the bound value of the target binding.

  1. Let envRec be the module Environment Record for which the method was invoked.
  2. Assert: envRec does not already have a binding for N.
  3. Assert: M is a Module Record.
  4. Assert: When M.[[Environment]] is instantiated it will have a direct binding for N2.
  5. Create an immutable indirect binding in envRec for N that references M and N2 as its target binding and record that the binding is initialized.
  6. Return NormalCompletion(empty).

8.1.2 Lexical Environment Operations

The following abstract operations are used in this specification to operate upon lexical environments:

8.1.2.1 GetIdentifierReference ( lex, name, strict )

The abstract operation GetIdentifierReference is called with a Lexical Environment lex, a String name, and a Boolean flag strict. The value of lex may be null. When called, the following steps are performed:

  1. If lex is the value null, then
    1. Return a value of type Reference whose base value component is undefined, whose referenced name component is name, and whose strict reference flag is strict.
  2. Let envRec be lex's EnvironmentRecord.
  3. Let exists be ? envRec.HasBinding(name).
  4. If exists is true, then
    1. Return a value of type Reference whose base value component is envRec, whose referenced name component is name, and whose strict reference flag is strict.
  5. Else,
    1. Let outer be the value of lex's outer environment reference.
    2. Return ? GetIdentifierReference(outer, name, strict).

8.1.2.2 NewDeclarativeEnvironment ( E )

When the abstract operation NewDeclarativeEnvironment is called with a Lexical Environment as argument E the following steps are performed:

  1. Let env be a new Lexical Environment.
  2. Let envRec be a new declarative Environment Record containing no bindings.
  3. Set env's EnvironmentRecord to envRec.
  4. Set the outer lexical environment reference of env to E.
  5. Return env.

8.1.2.3 NewObjectEnvironment ( O, E )

When the abstract operation NewObjectEnvironment is called with an Object O and a Lexical Environment E as arguments, the following steps are performed:

  1. Let env be a new Lexical Environment.
  2. Let envRec be a new object Environment Record containing O as the binding object.
  3. Set env's EnvironmentRecord to envRec.
  4. Set the outer lexical environment reference of env to E.
  5. Return env.

8.1.2.4 NewFunctionEnvironment ( F, newTarget )

When the abstract operation NewFunctionEnvironment is called with arguments F and newTarget the following steps are performed:

  1. Assert: F is an ECMAScript function.
  2. Assert: Type(newTarget) is Undefined or Object.
  3. Let env be a new Lexical Environment.
  4. Let envRec be a new function Environment Record containing no bindings.
  5. Set envRec.[[FunctionObject]] to F.
  6. If F.[[ThisMode]] is lexical, set envRec.[[ThisBindingStatus]] to "lexical".
  7. Else, set envRec.[[ThisBindingStatus]] to "uninitialized".
  8. Let home be F.[[HomeObject]].
  9. Set envRec.[[HomeObject]] to home.
  10. Set envRec.[[NewTarget]] to newTarget.
  11. Set env's EnvironmentRecord to envRec.
  12. Set the outer lexical environment reference of env to F.[[Environment]].
  13. Return env.

8.1.2.5 NewGlobalEnvironment ( G, thisValue )

When the abstract operation NewGlobalEnvironment is called with arguments G and thisValue, the following steps are performed:

  1. Let env be a new Lexical Environment.
  2. Let objRec be a new object Environment Record containing G as the binding object.
  3. Let dclRec be a new declarative Environment Record containing no bindings.
  4. Let globalRec be a new global Environment Record.
  5. Set globalRec.[[ObjectRecord]] to objRec.
  6. Set globalRec.[[GlobalThisValue]] to thisValue.
  7. Set globalRec.[[DeclarativeRecord]] to dclRec.
  8. Set globalRec.[[VarNames]] to a new empty List.
  9. Set env's EnvironmentRecord to globalRec.
  10. Set the outer lexical environment reference of env to null.
  11. Return env.

8.1.2.6 NewModuleEnvironment ( E )

When the abstract operation NewModuleEnvironment is called with a Lexical Environment argument E the following steps are performed:

  1. Let env be a new Lexical Environment.
  2. Let envRec be a new module Environment Record containing no bindings.
  3. Set env's EnvironmentRecord to envRec.
  4. Set the outer lexical environment reference of env to E.
  5. Return env.

8.2 Realms

Before it is evaluated, all ECMAScript code must be associated with a realm. Conceptually, a realm consists of a set of intrinsic objects, an ECMAScript global environment, all of the ECMAScript code that is loaded within the scope of that global environment, and other associated state and resources.

A realm is represented in this specification as a Realm Record with the fields specified in Table 20:

Table 20: Realm Record Fields
Field Name Value Meaning
[[Intrinsics]] Record whose field names are intrinsic keys and whose values are objects The intrinsic values used by code associated with this realm
[[GlobalObject]] Object The global object for this realm
[[GlobalEnv]] Lexical Environment The global environment for this realm
[[TemplateMap]] A List of Record { [[Site]]: Parse Node, [[Array]]: Object }.

Template objects are canonicalized separately for each realm using its Realm Record's [[TemplateMap]]. Each [[Site]] value is a Parse Node that is a TemplateLiteral. The associated [[Array]] value is the corresponding template object that is passed to a tag function.

Note
Once a Parse Node becomes unreachable, the corresponding [[Array]] is also unreachable, and it would be unobservable if an implementation removed the pair from the [[TemplateMap]] list.
[[HostDefined]] Any, default value is undefined. Field reserved for use by host environments that need to associate additional information with a Realm Record.

8.2.1 CreateRealm ( )

The abstract operation CreateRealm with no arguments performs the following steps:

  1. Let realmRec be a new Realm Record.
  2. Perform CreateIntrinsics(realmRec).
  3. Set realmRec.[[GlobalObject]] to undefined.
  4. Set realmRec.[[GlobalEnv]] to undefined.
  5. Set realmRec.[[TemplateMap]] to a new empty List.
  6. Return realmRec.

8.2.2 CreateIntrinsics ( realmRec )

The abstract operation CreateIntrinsics with argument realmRec performs the following steps:

  1. Let intrinsics be a new Record.
  2. Set realmRec.[[Intrinsics]] to intrinsics.
  3. Let objProto be ObjectCreate(null).
  4. Set intrinsics.[[%ObjectPrototype%]] to objProto.
  5. Let throwerSteps be the algorithm steps specified in 9.2.9.1 for the %ThrowTypeError% function.
  6. Let thrower be CreateBuiltinFunction(throwerSteps, « », realmRec, null).
  7. Set intrinsics.[[%ThrowTypeError%]] to thrower.
  8. Let noSteps be an empty sequence of algorithm steps.
  9. Let funcProto be CreateBuiltinFunction(noSteps, « », realmRec, objProto).
  10. Set intrinsics.[[%FunctionPrototype%]] to funcProto.
  11. Call thrower.[[SetPrototypeOf]](funcProto).
  12. Perform AddRestrictedFunctionProperties(funcProto, realmRec).
  13. Set fields of intrinsics with the values listed in Table 7 that have not already been handled above. The field names are the names listed in column one of the table. The value of each field is a new object value fully and recursively populated with property values as defined by the specification of each object in clauses 18-26. All object property values are newly created object values. All values that are built-in function objects are created by performing CreateBuiltinFunction(<steps>, <slots>, realmRec, <prototype>) where <steps> is the definition of that function provided by this specification, <slots> is a list of the names, if any, of the function's specified internal slots, and <prototype> is the specified value of the function's [[Prototype]] internal slot. The creation of the intrinsics and their properties must be ordered to avoid any dependencies upon objects that have not yet been created.
  14. Return intrinsics.

8.2.3 SetRealmGlobalObject ( realmRec, globalObj, thisValue )

The abstract operation SetRealmGlobalObject with arguments realmRec, globalObj, and thisValue performs the following steps:

  1. If globalObj is undefined, then
    1. Let intrinsics be realmRec.[[Intrinsics]].
    2. Set globalObj to ObjectCreate(intrinsics.[[%ObjectPrototype%]]).
  2. Assert: Type(globalObj) is Object.
  3. If thisValue is undefined, set thisValue to globalObj.
  4. Set realmRec.[[GlobalObject]] to globalObj.
  5. Let newGlobalEnv be NewGlobalEnvironment(globalObj, thisValue).
  6. Set realmRec.[[GlobalEnv]] to newGlobalEnv.
  7. Return realmRec.

8.2.4 SetDefaultGlobalBindings ( realmRec )

The abstract operation SetDefaultGlobalBindings with argument realmRec performs the following steps:

  1. Let global be realmRec.[[GlobalObject]].
  2. For each property of the Global Object specified in clause 18, do
    1. Let name be the String value of the property name.
    2. Let desc be the fully populated data property descriptor for the property containing the specified attributes for the property. For properties listed in 18.2, 18.3, or 18.4 the value of the [[Value]] attribute is the corresponding intrinsic object from realmRec.
    3. Perform ? DefinePropertyOrThrow(global, name, desc).
  3. Return global.

8.3 Execution Contexts

An execution context is a specification device that is used to track the runtime evaluation of code by an ECMAScript implementation. At any point in time, there is at most one execution context per agent that is actually executing code. This is known as the agent's running execution context. All references to the running execution context in this specification denote the running execution context of the surrounding agent.

The execution context stack is used to track execution contexts. The running execution context is always the top element of this stack. A new execution context is created whenever control is transferred from the executable code associated with the currently running execution context to executable code that is not associated with that execution context. The newly created execution context is pushed onto the stack and becomes the running execution context.

An execution context contains whatever implementation specific state is necessary to track the execution progress of its associated code. Each execution context has at least the state components listed in Table 21.

Table 21: State Components for All Execution Contexts
Component Purpose
code evaluation state Any state needed to perform, suspend, and resume evaluation of the code associated with this execution context.
Function If this execution context is evaluating the code of a function object, then the value of this component is that function object. If the context is evaluating the code of a Script or Module, the value is null.
Realm The Realm Record from which associated code accesses ECMAScript resources.
ScriptOrModule The Module Record or Script Record from which associated code originates. If there is no originating script or module, as is the case for the original execution context created in InitializeHostDefinedRealm, the value is null.

Evaluation of code by the running execution context may be suspended at various points defined within this specification. Once the running execution context has been suspended a different execution context may become the running execution context and commence evaluating its code. At some later time a suspended execution context may again become the running execution context and continue evaluating its code at the point where it had previously been suspended. Transition of the running execution context status among execution contexts usually occurs in stack-like last-in/first-out manner. However, some ECMAScript features require non-LIFO transitions of the running execution context.

The value of the Realm component of the running execution context is also called the current Realm Record. The value of the Function component of the running execution context is also called the active function object.

Execution contexts for ECMAScript code have the additional state components listed in Table 22.

Table 22: Additional State Components for ECMAScript Code Execution Contexts
Component Purpose
LexicalEnvironment Identifies the Lexical Environment used to resolve identifier references made by code within this execution context.
VariableEnvironment Identifies the Lexical Environment whose EnvironmentRecord holds bindings created by VariableStatements within this execution context.

The LexicalEnvironment and VariableEnvironment components of an execution context are always Lexical Environments.

Execution contexts representing the evaluation of generator objects have the additional state components listed in Table 23.

Table 23: Additional State Components for Generator Execution Contexts
Component Purpose
Generator The GeneratorObject that this execution context is evaluating.

In most situations only the running execution context (the top of the execution context stack) is directly manipulated by algorithms within this specification. Hence when the terms “LexicalEnvironment”, and “VariableEnvironment” are used without qualification they are in reference to those components of the running execution context.

An execution context is purely a specification mechanism and need not correspond to any particular artefact of an ECMAScript implementation. It is impossible for ECMAScript code to directly access or observe an execution context.

8.3.1 GetActiveScriptOrModule ( )

The GetActiveScriptOrModule abstract operation is used to determine the running script or module, based on the running execution context. GetActiveScriptOrModule performs the following steps:

  1. If the execution context stack is empty, return null.
  2. Let ec be the topmost execution context on the execution context stack whose ScriptOrModule component is not null.
  3. If no such execution context exists, return null. Otherwise, return ec's ScriptOrModule component.

8.3.2 ResolveBinding ( name [ , env ] )

The ResolveBinding abstract operation is used to determine the binding of name passed as a String value. The optional argument env can be used to explicitly provide the Lexical Environment that is to be searched for the binding. During execution of ECMAScript code, ResolveBinding is performed using the following algorithm:

  1. If env is not present or if env is undefined, then
    1. Set env to the running execution context's LexicalEnvironment.
  2. Assert: env is a Lexical Environment.
  3. If the code matching the syntactic production that is being evaluated is contained in strict mode code, let strict be true, else let strict be false.
  4. Return ? GetIdentifierReference(env, name, strict).
Note

The result of ResolveBinding is always a Reference value with its referenced name component equal to the name argument.

8.3.3 GetThisEnvironment ( )

The abstract operation GetThisEnvironment finds the Environment Record that currently supplies the binding of the keyword this. GetThisEnvironment performs the following steps:

  1. Let lex be the running execution context's LexicalEnvironment.
  2. Repeat,
    1. Let envRec be lex's EnvironmentRecord.
    2. Let exists be envRec.HasThisBinding().
    3. If exists is true, return envRec.
    4. Let outer be the value of lex's outer environment reference.
    5. Assert: outer is not null.
    6. Set lex to outer.
Note

The loop in step 2 will always terminate because the list of environments always ends with the global environment which has a this binding.

8.3.4 ResolveThisBinding ( )

The abstract operation ResolveThisBinding determines the binding of the keyword this using the LexicalEnvironment of the running execution context. ResolveThisBinding performs the following steps:

  1. Let envRec be GetThisEnvironment().
  2. Return ? envRec.GetThisBinding().

8.3.5 GetNewTarget ( )

The abstract operation GetNewTarget determines the NewTarget value using the LexicalEnvironment of the running execution context. GetNewTarget performs the following steps:

  1. Let envRec be GetThisEnvironment().
  2. Assert: envRec has a [[NewTarget]] field.
  3. Return envRec.[[NewTarget]].

8.3.6 GetGlobalObject ( )

The abstract operation GetGlobalObject returns the global object used by the currently running execution context. GetGlobalObject performs the following steps:

  1. Let ctx be the running execution context.
  2. Let currentRealm be ctx's Realm.
  3. Return currentRealm.[[GlobalObject]].

8.4 Jobs and Job Queues

A Job is an abstract operation that initiates an ECMAScript computation when no other ECMAScript computation is currently in progress. A Job abstract operation may be defined to accept an arbitrary set of job parameters.

Execution of a Job can be initiated only when there is no running execution context and the execution context stack is empty. A PendingJob is a request for the future execution of a Job. A PendingJob is an internal Record whose fields are specified in Table 24. Once execution of a Job is initiated, the Job always executes to completion. No other Job may be initiated until the currently running Job completes. However, the currently running Job or external events may cause the enqueuing of additional PendingJobs that may be initiated sometime after completion of the currently running Job.

Table 24: PendingJob Record Fields
Field Name Value Meaning
[[Job]] The name of a Job abstract operation This is the abstract operation that is performed when execution of this PendingJob is initiated.
[[Arguments]] A List The List of argument values that are to be passed to [[Job]] when it is activated.
[[Realm]] A Realm Record The Realm Record for the initial execution context when this PendingJob is initiated.
[[ScriptOrModule]] A Script Record or Module Record The script or module for the initial execution context when this PendingJob is initiated.
[[HostDefined]] Any, default value is undefined. Field reserved for use by host environments that need to associate additional information with a pending Job.

A Job Queue is a FIFO queue of PendingJob records. Each Job Queue has a name and the full set of available Job Queues are defined by an ECMAScript implementation. Every ECMAScript implementation has at least the Job Queues defined in Table 25.

Each agent has its own set of named Job Queues. All references to a named job queue in this specification denote the named job queue of the surrounding agent.

Table 25: Required Job Queues
Name Purpose
ScriptJobs Jobs that validate and evaluate ECMAScript Script and Module source text. See clauses 10 and 15.
PromiseJobs Jobs that are responses to the settlement of a Promise (see 25.6).

A request for the future execution of a Job is made by enqueueing, on a Job Queue, a PendingJob record that includes a Job abstract operation name and any necessary argument values. When there is no running execution context and the execution context stack is empty, the ECMAScript implementation removes the first PendingJob from a Job Queue and uses the information contained in it to create an execution context and starts execution of the associated Job abstract operation.

The PendingJob records from a single Job Queue are always initiated in FIFO order. This specification does not define the order in which multiple Job Queues are serviced. An ECMAScript implementation may interweave the FIFO evaluation of the PendingJob records of a Job Queue with the evaluation of the PendingJob records of one or more other Job Queues. An implementation must define what occurs when there are no running execution context and all Job Queues are empty.

Note

Typically an ECMAScript implementation will have its Job Queues pre-initialized with at least one PendingJob and one of those Jobs will be the first to be executed. An implementation might choose to free all resources and terminate if the current Job completes and all Job Queues are empty. Alternatively, it might choose to wait for a some implementation specific agent or mechanism to enqueue new PendingJob requests.

The following abstract operations are used to create and manage Jobs and Job Queues:

8.4.1 EnqueueJob ( queueName, job, arguments )

The EnqueueJob abstract operation requires three arguments: queueName, job, and arguments. It performs the following steps:

  1. Assert: Type(queueName) is String and its value is the name of a Job Queue recognized by this implementation.
  2. Assert: job is the name of a Job.
  3. Assert: arguments is a List that has the same number of elements as the number of parameters required by job.
  4. Let callerContext be the running execution context.
  5. Let callerRealm be callerContext's Realm.
  6. Let callerScriptOrModule be callerContext's ScriptOrModule.
  7. Let pending be PendingJob { [[Job]]: job, [[Arguments]]: arguments, [[Realm]]: callerRealm, [[ScriptOrModule]]: callerScriptOrModule, [[HostDefined]]: undefined }.
  8. Perform any implementation or host environment defined processing of pending. This may include modifying the [[HostDefined]] field or any other field of pending.
  9. Add pending at the back of the Job Queue named by queueName.
  10. Return NormalCompletion(empty).

8.5 InitializeHostDefinedRealm ( )

The abstract operation InitializeHostDefinedRealm performs the following steps:

  1. Let realm be CreateRealm().
  2. Let newContext be a new execution context.
  3. Set the Function of newContext to null.
  4. Set the Realm of newContext to realm.
  5. Set the ScriptOrModule of newContext to null.
  6. Push newContext onto the execution context stack; newContext is now the running execution context.
  7. If the host requires use of an exotic object to serve as realm's global object, let global be such an object created in an implementation-defined manner. Otherwise, let global be undefined, indicating that an ordinary object should be created as the global object.
  8. If the host requires that the this binding in realm's global scope return an object other than the global object, let thisValue be such an object created in an implementation-defined manner. Otherwise, let thisValue be undefined, indicating that realm's global this binding should be the global object.
  9. Perform SetRealmGlobalObject(realm, global, thisValue).
  10. Let globalObj be ? SetDefaultGlobalBindings(realm).
  11. Create any implementation-defined global object properties on globalObj.
  12. Return NormalCompletion(empty).

8.6 RunJobs ( )

The abstract operation RunJobs performs the following steps:

  1. Perform ? InitializeHostDefinedRealm().
  2. In an implementation-dependent manner, obtain the ECMAScript source texts (see clause 10) and any associated host-defined values for zero or more ECMAScript scripts and/or ECMAScript modules. For each such sourceText and hostDefined, do
    1. If sourceText is the source code of a script, then
      1. Perform EnqueueJob("ScriptJobs", ScriptEvaluationJob, « sourceText, hostDefined »).
    2. Else sourceText is the source code of a module,
      1. Perform EnqueueJob("ScriptJobs", TopLevelModuleEvaluationJob, « sourceText, hostDefined »).
  3. Repeat,
    1. Suspend the running execution context and remove it from the execution context stack.
    2. Assert: The execution context stack is now empty.
    3. Let nextQueue be a non-empty Job Queue chosen in an implementation-defined manner. If all Job Queues are empty, the result is implementation-defined.
    4. Let nextPending be the PendingJob record at the front of nextQueue. Remove that record from nextQueue.
    5. Let newContext be a new execution context.
    6. Set newContext's Function to null.
    7. Set newContext's Realm to nextPending.[[Realm]].
    8. Set newContext's ScriptOrModule to nextPending.[[ScriptOrModule]].
    9. Push newContext onto the execution context stack; newContext is now the running execution context.
    10. Perform any implementation or host environment defined job initialization using nextPending.
    11. Let result be the result of performing the abstract operation named by nextPending.[[Job]] using the elements of nextPending.[[Arguments]] as its arguments.
    12. If result is an abrupt completion, perform HostReportErrorsresult.[[Value]] »).

8.7 Agents

An agent comprises a set of ECMAScript execution contexts, an execution context stack, a running execution context, a set of named job queues, an Agent Record, and an executing thread. Except for the executing thread, the constituents of an agent belong exclusively to that agent.

An agent's executing thread executes the jobs in the agent's job queues on the agent's execution contexts independently of other agents, except that an executing thread may be used as the executing thread by multiple agents, provided none of the agents sharing the thread have an Agent Record whose [[CanBlock]] property is true.

Note 1

Some web browsers share a single executing thread across multiple unrelated tabs of a browser window, for example.

While an agent's executing thread executes the jobs in the agent's job queues, the agent is the surrounding agent for the code in those jobs. The code uses the surrounding agent to access the specification level execution objects held within the agent: the running execution context, the execution context stack, the named job queues, and the Agent Record's fields.

Table 26: Agent Record Fields
Field Name Value Meaning
[[LittleEndian]] Boolean The default value computed for the isLittleEndian parameter when it is needed by the algorithms GetValueFromBuffer and SetValueInBuffer. The choice is implementation-dependent and should be the alternative that is most efficient for the implementation. Once the value has been observed it cannot change.
[[CanBlock]] Boolean Determines whether the agent can block or not.
[[Signifier]] Any globally-unique value Uniquely identifies the agent within its agent cluster.
[[IsLockFree1]] Boolean true if atomic operations on one-byte values are lock-free, false otherwise.
[[IsLockFree2]] Boolean true if atomic operations on two-byte values are lock-free, false otherwise.
[[CandidateExecution]] A candidate execution Record See the memory model.

Once the values of [[Signifier]], [[IsLockFree1]], and [[IsLockFree2]] have been observed by any agent in the agent cluster they cannot change.

Note 2

The values of [[IsLockFree1]] and [[IsLockFree2]] are not necessarily determined by the hardware, but may also reflect implementation choices that can vary over time and between ECMAScript implementations.

There is no [[IsLockFree4]] property: 4-byte atomic operations are always lock-free.

In practice, if an atomic operation is implemented with any type of lock the operation is not lock-free. Lock-free does not imply wait-free: there is no upper bound on how many machine steps may be required to complete a lock-free atomic operation.

That an atomic access of size n is lock-free does not imply anything about the (perceived) atomicity of non-atomic accesses of size n, specifically, non-atomic accesses may still be performed as a sequence of several separate memory accesses. See ReadSharedMemory and WriteSharedMemory for details.

Note 3

An agent is a specification mechanism and need not correspond to any particular artefact of an ECMAScript implementation.

8.7.1 AgentSignifier ( )

The abstract operation AgentSignifier takes no arguments. It performs the following steps:

  1. Let AR be the Agent Record of the surrounding agent.
  2. Return AR.[[Signifier]].

8.7.2 AgentCanSuspend ( )

The abstract operation AgentCanSuspend takes no arguments. It performs the following steps:

  1. Let AR be the Agent Record of the surrounding agent.
  2. Return AR.[[CanBlock]].
Note

In some environments it may not be reasonable for a given agent to suspend. For example, in a web browser environment, it may be reasonable to disallow suspending a document's main event handling thread, while still allowing workers' event handling threads to suspend.

8.8 Agent Clusters

An agent cluster is a maximal set of agents that can communicate by operating on shared memory.

Note 1

Programs within different agents may share memory by unspecified means. At a minimum, the backing memory for SharedArrayBuffer objects can be shared among the agents in the cluster.

There may be agents that can communicate by message passing that cannot share memory; they are never in the same agent cluster.

Every agent belongs to exactly one agent cluster.

Note 2

The agents in a cluster need not all be alive at some particular point in time. If agent A creates another agent B, after which A terminates and B creates agent C, the three agents are in the same cluster if A could share some memory with B and B could share some memory with C.

All agents within a cluster must have the same value for the [[LittleEndian]] property in their respective Agent Records.

Note 3

If different agents within an agent cluster have different values of [[LittleEndian]] it becomes hard to use shared memory for multi-byte data.

All agents within a cluster must have the same values for the [[IsLockFree1]] property in their respective Agent Records; similarly for the [[IsLockFree2]] property.

All agents within a cluster must have different values for the [[Signifier]] property in their respective Agent Records.

An embedding may deactivate (stop forward progress) or activate (resume forward progress) an agent without the agent's knowledge or cooperation. If the embedding does so, it must not leave some agents in the cluster active while other agents in the cluster are deactivated indefinitely.

Note 4

The purpose of the preceding restriction is to avoid a situation where an agent deadlocks or starves because another agent has been deactivated. For example, if an HTML shared worker that has a lifetime independent of documents in any windows were allowed to share memory with the dedicated worker of such an independent document, and the document and its dedicated worker were to be deactivated while the dedicated worker holds a lock (say, the document is pushed into its window's history), and the shared worker then tries to acquire the lock, then the shared worker will be blocked until the dedicated worker is activated again, if ever. Meanwhile other workers trying to access the shared worker from other windows will starve.

The implication of the restriction is that it will not be possible to share memory between agents that don't belong to the same suspend/wake collective within the embedding.

An embedding may terminate an agent without any of the agent's cluster's other agents' prior knowledge or cooperation. If an agent is terminated not by programmatic action of its own or of another agent in the cluster but by forces external to the cluster, then the embedding must choose one of two strategies: Either terminate all the agents in the cluster, or provide reliable APIs that allow the agents in the cluster to coordinate so that at least one remaining member of the cluster will be able to detect the termination, with the termination data containing enough information to identify the agent that was terminated.

Note 5

Examples of that type of termination are: operating systems or users terminating agents that are running in separate processes; the embedding itself terminating an agent that is running in-process with the other agents when per-agent resource accounting indicates that the agent is runaway.

Prior to any evaluation of any ECMAScript code by any agent in a cluster, the [[CandidateExecution]] field of the Agent Record for all agents in the cluster is set to the initial candidate execution. The initial candidate execution is an empty candidate execution whose [[EventLists]] field is a List containing, for each agent, an Agent Events Record whose [[AgentSignifier]] field is that agent's signifier and whose [[EventList]] field is an empty List.

Note 6

All agents in an agent cluster share the same candidate execution in its Agent Record's [[CandidateExecution]] field. The candidate execution is a specification mechanism used by the memory model.

Note 7

An agent cluster is a specification mechanism and need not correspond to any particular artefact of an ECMAScript implementation.

8.9 Forward Progress

For an agent to make forward progress is for it to perform an evaluation step according to this specification.

An agent becomes blocked when its running execution context waits synchronously and indefinitely for an external event. Only agents whose Agent Record's [[CanBlock]] property is true can become blocked in this sense. An unblocked agent is one that is not blocked.

Implementations must ensure that:

  • every unblocked agent with a dedicated executing thread eventually makes forward progress
  • in a set of agents that share an executing thread, one agent eventually makes forward progress
  • an agent does not cause another agent to become blocked except via explicit APIs that provide blocking.
Note

This, along with the liveness guarantee in the memory model, ensures that all "SeqCst" writes eventually become observable to all agents.

9 Ordinary and Exotic Objects Behaviours

9.1 Ordinary Object Internal Methods and Internal Slots

All ordinary objects have an internal slot called [[Prototype]]. The value of this internal slot is either null or an object and is used for implementing inheritance. Data properties of the [[Prototype]] object are inherited (and visible as properties of the child object) for the purposes of get access, but not for set access. Accessor properties are inherited for both get access and set access.

Every ordinary object has a Boolean-valued [[Extensible]] internal slot that controls whether or not properties may be added to the object. If the value of the [[Extensible]] internal slot is false then additional properties may not be added to the object. In addition, if [[Extensible]] is false the value of the [[Prototype]] internal slot of the object may not be modified. Once the value of an object's [[Extensible]] internal slot has been set to false it may not be subsequently changed to true.

In the following algorithm descriptions, assume O is an ordinary object, P is a property key value, V is any ECMAScript language value, and Desc is a Property Descriptor record.

Each ordinary object internal method delegates to a similarly-named abstract operation. If such an abstract operation depends on another internal method, then the internal method is invoked on O rather than calling the similarly-named abstract operation directly. These semantics ensure that exotic objects have their overridden internal methods invoked when ordinary object internal methods are applied to them.

9.1.1 [[GetPrototypeOf]] ( )

When the [[GetPrototypeOf]] internal method of O is called, the following steps are taken:

  1. Return ! OrdinaryGetPrototypeOf(O).

9.1.1.1 OrdinaryGetPrototypeOf ( O )

When the abstract operation OrdinaryGetPrototypeOf is called with Object O, the following steps are taken:

  1. Return O.[[Prototype]].

9.1.2 [[SetPrototypeOf]] ( V )

When the [[SetPrototypeOf]] internal method of O is called with argument V, the following steps are taken:

  1. Return ! OrdinarySetPrototypeOf(O, V).

9.1.2.1 OrdinarySetPrototypeOf ( O, V )

When the abstract operation OrdinarySetPrototypeOf is called with Object O and value V, the following steps are taken:

  1. Assert: Either Type(V) is Object or Type(V) is Null.
  2. Let extensible be O.[[Extensible]].
  3. Let current be O.[[Prototype]].
  4. If SameValue(V, current) is true, return true.
  5. If extensible is false, return false.
  6. Let p be V.
  7. Let done be false.
  8. Repeat, while done is false,
    1. If p is null, set done to true.
    2. Else if SameValue(p, O) is true, return false.
    3. Else,
      1. If p.[[GetPrototypeOf]] is not the ordinary object internal method defined in 9.1.1, set done to true.
      2. Else, set p to p.[[Prototype]].
  9. Set O.[[Prototype]] to V.
  10. Return true.
Note

The loop in step 8 guarantees that there will be no circularities in any prototype chain that only includes objects that use the ordinary object definitions for [[GetPrototypeOf]] and [[SetPrototypeOf]].

9.1.3 [[IsExtensible]] ( )

When the [[IsExtensible]] internal method of O is called, the following steps are taken:

  1. Return ! OrdinaryIsExtensible(O).

9.1.3.1 OrdinaryIsExtensible ( O )

When the abstract operation OrdinaryIsExtensible is called with Object O, the following steps are taken:

  1. Return O.[[Extensible]].

9.1.4 [[PreventExtensions]] ( )

When the [[PreventExtensions]] internal method of O is called, the following steps are taken:

  1. Return ! OrdinaryPreventExtensions(O).

9.1.4.1 OrdinaryPreventExtensions ( O )

When the abstract operation OrdinaryPreventExtensions is called with Object O, the following steps are taken:

  1. Set O.[[Extensible]] to false.
  2. Return true.

9.1.5 [[GetOwnProperty]] ( P )

When the [[GetOwnProperty]] internal method of O is called with property key P, the following steps are taken:

  1. Return ! OrdinaryGetOwnProperty(O, P).

9.1.5.1 OrdinaryGetOwnProperty ( O, P )

When the abstract operation OrdinaryGetOwnProperty is called with Object O and with property key P, the following steps are taken:

  1. Assert: IsPropertyKey(P) is true.
  2. If O does not have an own property with key P, return undefined.
  3. Let D be a newly created Property Descriptor with no fields.
  4. Let X be O's own property whose key is P.
  5. If X is a data property, then
    1. Set D.[[Value]] to the value of X's [[Value]] attribute.
    2. Set D.[[Writable]] to the value of X's [[Writable]] attribute.
  6. Else X is an accessor property,
    1. Set D.[[Get]] to the value of X's [[Get]] attribute.
    2. Set D.[[Set]] to the value of X's [[Set]] attribute.
  7. Set D.[[Enumerable]] to the value of X's [[Enumerable]] attribute.
  8. Set D.[[Configurable]] to the value of X's [[Configurable]] attribute.
  9. Return D.

9.1.6 [[DefineOwnProperty]] ( P, Desc )

When the [[DefineOwnProperty]] internal method of O is called with property key P and Property Descriptor Desc, the following steps are taken:

  1. Return ? OrdinaryDefineOwnProperty(O, P, Desc).

9.1.6.1 OrdinaryDefineOwnProperty ( O, P, Desc )

When the abstract operation OrdinaryDefineOwnProperty is called with Object O, property key P, and Property Descriptor Desc, the following steps are taken:

  1. Let current be ? O.[[GetOwnProperty]](P).
  2. Let extensible be O.[[Extensible]].
  3. Return ValidateAndApplyPropertyDescriptor(O, P, extensible, Desc, current).

9.1.6.2 IsCompatiblePropertyDescriptor ( Extensible, Desc, Current )

When the abstract operation IsCompatiblePropertyDescriptor is called with Boolean value Extensible, and Property Descriptors Desc, and Current, the following steps are taken:

  1. Return ValidateAndApplyPropertyDescriptor(undefined, undefined, Extensible, Desc, Current).

9.1.6.3 ValidateAndApplyPropertyDescriptor ( O, P, extensible, Desc, current )

When the abstract operation ValidateAndApplyPropertyDescriptor is called with Object O, property key P, Boolean value extensible, and Property Descriptors Desc, and current, the following steps are taken:

Note

If undefined is passed as O, only validation is performed and no object updates are performed.

  1. Assert: If O is not undefined, then IsPropertyKey(P) is true.
  2. If current is undefined, then
    1. If extensible is false, return false.
    2. Assert: extensible is true.
    3. If IsGenericDescriptor(Desc) is true or IsDataDescriptor(Desc) is true, then
      1. If O is not undefined, create an own data property named P of object O whose [[Value]], [[Writable]], [[Enumerable]] and [[Configurable]] attribute values are described by Desc. If the value of an attribute field of Desc is absent, the attribute of the newly created property is set to its default value.
    4. Else Desc must be an accessor Property Descriptor,
      1. If O is not undefined, create an own accessor property named P of object O whose [[Get]], [[Set]], [[Enumerable]] and [[Configurable]] attribute values are described by Desc. If the value of an attribute field of Desc is absent, the attribute of the newly created property is set to its default value.
    5. Return true.
  3. If every field in Desc is absent, return true.
  4. If current.[[Configurable]] is false, then
    1. If Desc.[[Configurable]] is present and its value is true, return false.
    2. If Desc.[[Enumerable]] is present and the [[Enumerable]] fields of current and Desc are the Boolean negation of each other, return false.
  5. If IsGenericDescriptor(Desc) is true, no further validation is required.
  6. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) have different results, then
    1. If current.[[Configurable]] is false, return false.
    2. If IsDataDescriptor(current) is true, then
      1. If O is not undefined, convert the property named P of object O from a data property to an accessor property. Preserve the existing values of the converted property's [[Configurable]] and [[Enumerable]] attributes and set the rest of the property's attributes to their default values.
    3. Else,
      1. If O is not undefined, convert the property named P of object O from an accessor property to a data property. Preserve the existing values of the converted property's [[Configurable]] and [[Enumerable]] attributes and set the rest of the property's attributes to their default values.
  7. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) are both true, then
    1. If current.[[Configurable]] is false and current.[[Writable]] is false, then
      1. If Desc.[[Writable]] is present and Desc.[[Writable]] is true, return false.
      2. If Desc.[[Value]] is present and SameValue(Desc.[[Value]], current.[[Value]]) is false, return false.
      3. Return true.
  8. Else IsAccessorDescriptor(current) and IsAccessorDescriptor(Desc) are both true,
    1. If current.[[Configurable]] is false, then
      1. If Desc.[[Set]] is present and SameValue(Desc.[[Set]], current.[[Set]]) is false, return false.
      2. If Desc.[[Get]] is present and SameValue(Desc.[[Get]], current.[[Get]]) is false, return false.
      3. Return true.
  9. If O is not undefined, then
    1. For each field of Desc that is present, set the corresponding attribute of the property named P of object O to the value of the field.
  10. Return true.

9.1.7 [[HasProperty]] ( P )

When the [[HasProperty]] internal method of O is called with property key P, the following steps are taken:

  1. Return ? OrdinaryHasProperty(O, P).

9.1.7.1 OrdinaryHasProperty ( O, P )

When the abstract operation OrdinaryHasProperty is called with Object O and with property key P, the following steps are taken:

  1. Assert: IsPropertyKey(P) is true.
  2. Let hasOwn be ? O.[[GetOwnProperty]](P).
  3. If hasOwn is not undefined, return true.
  4. Let parent be ? O.[[GetPrototypeOf]]().
  5. If parent is not null, then
    1. Return ? parent.[[HasProperty]](P).
  6. Return false.

9.1.8 [[Get]] ( P, Receiver )

When the [[Get]] internal method of O is called with property key P and ECMAScript language value Receiver, the following steps are taken:

  1. Return ? OrdinaryGet(O, P, Receiver).

9.1.8.1 OrdinaryGet ( O, P, Receiver )

When the abstract operation OrdinaryGet is called with Object O, property key P, and ECMAScript language value Receiver, the following steps are taken:

  1. Assert: IsPropertyKey(P) is true.
  2. Let desc be ? O.[[GetOwnProperty]](P).
  3. If desc is undefined, then
    1. Let parent be ? O.[[GetPrototypeOf]]().
    2. If parent is null, return undefined.
    3. Return ? parent.[[Get]](P, Receiver).
  4. If IsDataDescriptor(desc) is true, return desc.[[Value]].
  5. Assert: IsAccessorDescriptor(desc) is true.
  6. Let getter be desc.[[Get]].
  7. If getter is undefined, return undefined.
  8. Return ? Call(getter, Receiver).

9.1.9 [[Set]] ( P, V, Receiver )

When the [[Set]] internal method of O is called with property key P, value V, and ECMAScript language value Receiver, the following steps are taken:

  1. Return ? OrdinarySet(O, P, V, Receiver).

9.1.9.1 OrdinarySet ( O, P, V, Receiver )

When the abstract operation OrdinarySet is called with Object O, property key P, value V, and ECMAScript language value Receiver, the following steps are taken:

  1. Assert: IsPropertyKey(P) is true.
  2. Let ownDesc be ? O.[[GetOwnProperty]](P).
  3. Return OrdinarySetWithOwnDescriptor(O, P, V, Receiver, ownDesc).

9.1.9.2 OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc )

When the abstract operation OrdinarySetWithOwnDescriptor is called with Object O, property key P, value V, ECMAScript language value Receiver, and Property Descriptor (or undefined) ownDesc, the following steps are taken:

  1. Assert: IsPropertyKey(P) is true.
  2. If ownDesc is undefined, then
    1. Let parent be ? O.[[GetPrototypeOf]]().
    2. If parent is not null, then
      1. Return ? parent.[[Set]](P, V, Receiver).
    3. Else,
      1. Set ownDesc to the PropertyDescriptor { [[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }.
  3. If IsDataDescriptor(ownDesc) is true, then
    1. If ownDesc.[[Writable]] is false, return false.
    2. If Type(Receiver) is not Object, return false.
    3. Let existingDescriptor be ? Receiver.[[GetOwnProperty]](P).
    4. If existingDescriptor is not undefined, then
      1. If IsAccessorDescriptor(existingDescriptor) is true, return false.
      2. If existingDescriptor.[[Writable]] is false, return false.
      3. Let valueDesc be the PropertyDescriptor { [[Value]]: V }.
      4. Return ? Receiver.[[DefineOwnProperty]](P, valueDesc).
    5. Else Receiver does not currently have a property P,
      1. Return ? CreateDataProperty(Receiver, P, V).
  4. Assert: IsAccessorDescriptor(ownDesc) is true.
  5. Let setter be ownDesc.[[Set]].
  6. If setter is undefined, return false.
  7. Perform ? Call(setter, Receiver, « V »).
  8. Return true.

9.1.10 [[Delete]] ( P )

When the [[Delete]] internal method of O is called with property key P, the following steps are taken:

  1. Return ? OrdinaryDelete(O, P).

9.1.10.1 OrdinaryDelete ( O, P )

When the abstract operation OrdinaryDelete is called with Object O and property key P, the following steps are taken:

  1. Assert: IsPropertyKey(P) is true.
  2. Let desc be ? O.[[GetOwnProperty]](P).
  3. If desc is undefined, return true.
  4. If desc.[[Configurable]] is true, then
    1. Remove the own property with name P from O.
    2. Return true.
  5. Return false.

9.1.11 [[OwnPropertyKeys]] ( )

When the [[OwnPropertyKeys]] internal method of O is called, the following steps are taken:

  1. Return ! OrdinaryOwnPropertyKeys(O).

9.1.11.1 OrdinaryOwnPropertyKeys ( O )

When the abstract operation OrdinaryOwnPropertyKeys is called with Object O, the following steps are taken:

  1. Let keys be a new empty List.
  2. For each own property key P of O that is an integer index, in ascending numeric index order, do
    1. Add P as the last element of keys.
  3. For each own property key P of O that is a String but is not an integer index, in ascending chronological order of property creation, do
    1. Add P as the last element of keys.
  4. For each own property key P of O that is a Symbol, in ascending chronological order of property creation, do
    1. Add P as the last element of keys.
  5. Return keys.

9.1.12 ObjectCreate ( proto [ , internalSlotsList ] )

The abstract operation ObjectCreate with argument proto (an object or null) is used to specify the runtime creation of new ordinary objects. The optional argument internalSlotsList is a List of the names of additional internal slots that must be defined as part of the object. If the list is not provided, a new empty List is used. This abstract operation performs the following steps:

  1. If internalSlotsList is not present, set internalSlotsList to a new empty List.
  2. Let obj be a newly created object with an internal slot for each name in internalSlotsList.
  3. Set obj's essential internal methods to the default ordinary object definitions specified in 9.1.
  4. Set obj.[[Prototype]] to proto.
  5. Set obj.[[Extensible]] to true.
  6. Return obj.

9.1.13 OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] )

The abstract operation OrdinaryCreateFromConstructor creates an ordinary object whose [[Prototype]] value is retrieved from a constructor's prototype property, if it exists. Otherwise the intrinsic named by intrinsicDefaultProto is used for [[Prototype]]. The optional internalSlotsList is a List of the names of additional internal slots that must be defined as part of the object. If the list is not provided, a new empty List is used. This abstract operation performs the following steps:

  1. Assert: intrinsicDefaultProto is a String value that is this specification's name of an intrinsic object. The corresponding object must be an intrinsic that is intended to be used as the [[Prototype]] value of an object.
  2. Let proto be ? GetPrototypeFromConstructor(constructor, intrinsicDefaultProto).
  3. Return ObjectCreate(proto, internalSlotsList).

9.1.14 GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto )

The abstract operation GetPrototypeFromConstructor determines the [[Prototype]] value that should be used to create an object corresponding to a specific constructor. The value is retrieved from the constructor's prototype property, if it exists. Otherwise the intrinsic named by intrinsicDefaultProto is used for [[Prototype]]. This abstract operation performs the following steps:

  1. Assert: intrinsicDefaultProto is a String value that is this specification's name of an intrinsic object. The corresponding object must be an intrinsic that is intended to be used as the [[Prototype]] value of an object.
  2. Assert: IsCallable(constructor) is true.
  3. Let proto be ? Get(constructor, "prototype").
  4. If Type(proto) is not Object, then
    1. Let realm be ? GetFunctionRealm(constructor).
    2. Set proto to realm's intrinsic object named intrinsicDefaultProto.
  5. Return proto.
Note

If constructor does not supply a [[Prototype]] value, the default value that is used is obtained from the realm of the constructor function rather than from the running execution context.

9.2 ECMAScript Function Objects

ECMAScript function objects encapsulate parameterized ECMAScript code closed over a lexical environment and support the dynamic evaluation of that code. An ECMAScript function object is an ordinary object and has the same internal slots and the same internal methods as other ordinary objects. The code of an ECMAScript function object may be either strict mode code (10.2.1) or non-strict code. An ECMAScript function object whose code is strict mode code is called a strict function. One whose code is not strict mode code is called a non-strict function.

ECMAScript function objects have the additional internal slots listed in Table 27.

Table 27: Internal Slots of ECMAScript Function Objects
Internal Slot Type Description
[[Environment]] Lexical Environment The Lexical Environment that the function was closed over. Used as the outer environment when evaluating the code of the function.
[[FormalParameters]] Parse Node The root parse node of the source text that defines the function's formal parameter list.
[[FunctionKind]] String Either "normal", "classConstructor", "generator", or "async".
[[ECMAScriptCode]] Parse Node The root parse node of the source text that defines the function's body.
[[ConstructorKind]] String Either "base" or "derived".
[[Realm]] Realm Record The realm in which the function was created and which provides any intrinsic objects that are accessed when evaluating the function.
[[ScriptOrModule]] Script Record or Module Record The script or module in which the function was created.
[[ThisMode]] (lexical, strict, global) Defines how this references are interpreted within the formal parameters and code body of the function. lexical means that this refers to the this value of a lexically enclosing function. strict means that the this value is used exactly as provided by an invocation of the function. global means that a this value of undefined is interpreted as a reference to the global object.
[[Strict]] Boolean true if this is a strict function, false if this is a non-strict function.
[[HomeObject]] Object If the function uses super, this is the object whose [[GetPrototypeOf]] provides the object where super property lookups begin.

All ECMAScript function objects have the [[Call]] internal method defined here. ECMAScript functions that are also constructors in addition have the [[Construct]] internal method.

9.2.1 [[Call]] ( thisArgument, argumentsList )

The [[Call]] internal method for an ECMAScript function object F is called with parameters thisArgument and argumentsList, a List of ECMAScript language values. The following steps are taken:

  1. Assert: F is an ECMAScript function object.
  2. If F.[[FunctionKind]] is "classConstructor", throw a TypeError exception.
  3. Let callerContext be the running execution context.
  4. Let calleeContext be PrepareForOrdinaryCall(F, undefined).
  5. Assert: calleeContext is now the running execution context.
  6. Perform OrdinaryCallBindThis(F, calleeContext, thisArgument).
  7. Let result be OrdinaryCallEvaluateBody(F, argumentsList).
  8. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
  9. If result.[[Type]] is return, return NormalCompletion(result.[[Value]]).
  10. ReturnIfAbrupt(result).
  11. Return NormalCompletion(undefined).
Note

When calleeContext is removed from the execution context stack in step 8 it must not be destroyed if it is suspended and retained for later resumption by an accessible generator object.

9.2.1.1 PrepareForOrdinaryCall ( F, newTarget )

When the abstract operation PrepareForOrdinaryCall is called with function object F and ECMAScript language value newTarget, the following steps are taken:

  1. Assert: Type(newTarget) is Undefined or Object.
  2. Let callerContext be the running execution context.
  3. Let calleeContext be a new ECMAScript code execution context.
  4. Set the Function of calleeContext to F.
  5. Let calleeRealm be F.[[Realm]].
  6. Set the Realm of calleeContext to calleeRealm.
  7. Set the ScriptOrModule of calleeContext to F.[[ScriptOrModule]].
  8. Let localEnv be NewFunctionEnvironment(F, newTarget).
  9. Set the LexicalEnvironment of calleeContext to localEnv.
  10. Set the VariableEnvironment of calleeContext to localEnv.
  11. If callerContext is not already suspended, suspend callerContext.
  12. Push calleeContext onto the execution context stack; calleeContext is now the running execution context.
  13. NOTE: Any exception objects produced after this point are associated with calleeRealm.
  14. Return calleeContext.

9.2.1.2 OrdinaryCallBindThis ( F, calleeContext, thisArgument )

When the abstract operation OrdinaryCallBindThis is called with function object F, execution context calleeContext, and ECMAScript value thisArgument, the following steps are taken:

  1. Let thisMode be F.[[ThisMode]].
  2. If thisMode is lexical, return NormalCompletion(undefined).
  3. Let calleeRealm be F.[[Realm]].
  4. Let localEnv be the LexicalEnvironment of calleeContext.
  5. If thisMode is strict, let thisValue be thisArgument.
  6. Else,
    1. If thisArgument is undefined or null, then
      1. Let globalEnv be calleeRealm.[[GlobalEnv]].
      2. Let globalEnvRec be globalEnv's EnvironmentRecord.
      3. Assert: globalEnvRec is a global Environment Record.
      4. Let thisValue be globalEnvRec.[[GlobalThisValue]].
    2. Else,
      1. Let thisValue be ! ToObject(thisArgument).
      2. NOTE: ToObject produces wrapper objects using calleeRealm.
  7. Let envRec be localEnv's EnvironmentRecord.
  8. Assert: envRec is a function Environment Record.
  9. Assert: The next step never returns an abrupt completion because envRec.[[ThisBindingStatus]] is not "initialized".
  10. Return envRec.BindThisValue(thisValue).

9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList )

When the abstract operation OrdinaryCallEvaluateBody is called with function object F and List argumentsList, the following steps are taken:

  1. Return the result of EvaluateBody of the parsed code that is F.[[ECMAScriptCode]] passing F and argumentsList as the arguments.

9.2.2 [[Construct]] ( argumentsList, newTarget )

The [[Construct]] internal method for an ECMAScript function object F is called with parameters argumentsList and newTarget. argumentsList is a possibly empty List of ECMAScript language values. The following steps are taken:

  1. Assert: F is an ECMAScript function object.
  2. Assert: Type(newTarget) is Object.
  3. Let callerContext be the running execution context.
  4. Let kind be F.[[ConstructorKind]].
  5. If kind is "base", then
    1. Let thisArgument be ? OrdinaryCreateFromConstructor(newTarget, "%ObjectPrototype%").
  6. Let calleeContext be PrepareForOrdinaryCall(F, newTarget).
  7. Assert: calleeContext is now the running execution context.
  8. If kind is "base", perform OrdinaryCallBindThis(F, calleeContext, thisArgument).
  9. Let constructorEnv be the LexicalEnvironment of calleeContext.
  10. Let envRec be constructorEnv's EnvironmentRecord.
  11. Let result be OrdinaryCallEvaluateBody(F, argumentsList).
  12. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
  13. If result.[[Type]] is return, then
    1. If Type(result.[[Value]]) is Object, return NormalCompletion(result.[[Value]]).
    2. If kind is "base", return NormalCompletion(thisArgument).
    3. If result.[[Value]] is not undefined, throw a TypeError exception.
  14. Else, ReturnIfAbrupt(result).
  15. Return ? envRec.GetThisBinding().

9.2.3 FunctionAllocate ( functionPrototype, strict, functionKind )

The abstract operation FunctionAllocate requires the three arguments functionPrototype, strict and functionKind. FunctionAllocate performs the following steps:

  1. Assert: Type(functionPrototype) is Object.
  2. Assert: functionKind is either "normal", "non-constructor", "generator", "async", or "async generator".
  3. If functionKind is "normal", let needsConstruct be true.
  4. Else, let needsConstruct be false.
  5. If functionKind is "non-constructor", set functionKind to "normal".
  6. Let F be a newly created ECMAScript function object with the internal slots listed in Table 27. All of those internal slots are initialized to undefined.
  7. Set F's essential internal methods to the default ordinary object definitions specified in 9.1.
  8. Set F.[[Call]] to the definition specified in 9.2.1.
  9. If needsConstruct is true, then
    1. Set F.[[Construct]] to the definition specified in 9.2.2.
    2. Set F.[[ConstructorKind]] to "base".
  10. Set F.[[Strict]] to strict.
  11. Set F.[[FunctionKind]] to functionKind.
  12. Set F.[[Prototype]] to functionPrototype.
  13. Set F.[[Extensible]] to true.
  14. Set F.[[Realm]] to the current Realm Record.
  15. Return F.

9.2.4 FunctionInitialize ( F, kind, ParameterList, Body, Scope )

The abstract operation FunctionInitialize requires the arguments: a function object F, kind which is one of (Normal, Method, Arrow), a parameter list Parse Node specified by ParameterList, a body Parse Node specified by Body, a Lexical Environment specified by Scope. FunctionInitialize performs the following steps:

  1. Let len be the ExpectedArgumentCount of ParameterList.
  2. Perform ! SetFunctionLength(F, len).
  3. Let Strict be F.[[Strict]].
  4. Set F.[[Environment]] to Scope.
  5. Set F.[[FormalParameters]] to ParameterList.
  6. Set F.[[ECMAScriptCode]] to Body.
  7. Set F.[[ScriptOrModule]] to GetActiveScriptOrModule().
  8. If kind is Arrow, set F.[[ThisMode]] to lexical.
  9. Else if Strict is true, set F.[[ThisMode]] to strict.
  10. Else, set F.[[ThisMode]] to global.
  11. Return F.

9.2.5 FunctionCreate ( kind, ParameterList, Body, Scope, Strict [ , prototype ] )

The abstract operation FunctionCreate requires the arguments: kind which is one of (Normal, Method, Arrow), a parameter list Parse Node specified by ParameterList, a body Parse Node specified by Body, a Lexical Environment specified by Scope, a Boolean flag Strict, and optionally, an object prototype. FunctionCreate performs the following steps:

  1. If prototype is not present, then
    1. Set prototype to the intrinsic object %FunctionPrototype%.
  2. If kind is not Normal, let allocKind be "non-constructor".
  3. Else, let allocKind be "normal".
  4. Let F be FunctionAllocate(prototype, Strict, allocKind).
  5. Return FunctionInitialize(F, kind, ParameterList, Body, Scope).

9.2.6 GeneratorFunctionCreate ( kind, ParameterList, Body, Scope, Strict )

The abstract operation GeneratorFunctionCreate requires the arguments: kind which is one of (Normal, Method), a parameter list