4 概述
本节包含 ECMAScript 语言的非规范性概述。
ECMAScript 是一种面向对象的编程语言,用于在宿主环境 中执行计算并操作计算对象。此处定义的 ECMAScript 并不意在计算上自给自足;实际上,本规范中没有关于外部数据输入或计算结果输出的规定。相反,预期 ECMAScript 程序的计算环境不仅会提供本规范中描述的对象和其他设施,还会提供某些环境特定对象;除说明这些对象可以提供某些可被访问的属性以及某些可由 ECMAScript 程序调用的函数外,对这些对象的描述和行为均超出本规范范围。
ECMAScript 最初被设计为一种脚本语言使用,但已被广泛用作通用编程语言。脚本语言 是一种用于操纵、自定义和自动化既有系统设施的编程语言。在这样的系统中,有用的功能已经通过用户界面可用,而脚本语言是一种将该功能暴露给程序控制的机制。通过这种方式,可以说既有系统提供了由对象和设施构成的宿主环境 ,从而补全脚本语言的能力。脚本语言旨在供专业和非专业程序员使用。
ECMAScript 最初被设计为一种 Web 脚本语言 ,提供一种机制,用于在浏览器中使 Web 页面生动起来,并作为基于 Web 的客户端-服务器架构的一部分执行服务器计算。ECMAScript 现在被用于为各种宿主环境 提供核心脚本能力。因此,本文档在脱离任何特定宿主环境 的情况下规定核心语言。
ECMAScript 的使用已超越简单脚本,现在被用于许多不同环境和规模中的全部编程任务范围。随着 ECMAScript 使用范围的扩大,它所提供的特性和设施也随之扩展。ECMAScript 现在是一种功能完备的通用编程语言。
4.1 Web 脚本
Web 浏览器为客户端计算提供 ECMAScript 宿主环境 ,其中包括例如表示窗口、菜单、弹出窗口、对话框、文本区域、锚点、框架、历史、cookie 以及输入/输出的对象。此外,宿主环境 还提供一种手段,用于将脚本代码附加到焦点变化、页面和图像加载、卸载、错误和中止、选择、表单提交以及鼠标动作等事件。脚本代码出现在 HTML 中,而所显示的页面是用户界面元素以及固定和计算得到的文本与图像的组合。脚本代码对用户交互作出反应,并且不需要主程序。
Web 服务器为服务器端计算提供不同的宿主环境 ,其中包括表示请求、客户端和文件的对象;以及用于锁定和共享数据的机制。通过同时使用浏览器端和服务器端脚本,可以在客户端和服务器之间分配计算,同时为基于 Web 的应用程序提供自定义用户界面。
每个支持 ECMAScript 的 Web 浏览器和服务器都提供其自身的宿主环境 ,从而补全 ECMAScript 执行环境。
4.2 宿主和实现
为辅助将 ECMAScript 集成到宿主环境 中,本规范将某些设施(例如抽象操作 )的定义,整体或部分地推迟到本规范之外的来源。编辑上,本规范区分以下几类推迟定义。
实现 是一个外部来源,它进一步定义附录 D 中列举的设施,或那些被标记为实现定义或实现近似的 设施。在非正式用法中,实现指一个具体制品,例如某个特定 Web 浏览器。
实现定义的 设施,是指其定义无进一步限定地推迟给外部来源的设施。本规范不对特定行为作出任何建议,一致实现可在本规范提出的约束范围内自由选择任何行为。
实现近似的 设施,是指其定义推迟给外部来源、同时本规范推荐理想行为的设施。虽然一致实现可在本规范提出的约束范围内自由选择任何行为,但鼓励它们努力近似该理想行为。一些数学操作,例如 Math.exp ,是实现近似的 。
宿主 是一个外部来源,它进一步定义附录 D 中列出的设施,但不进一步定义其他实现定义或实现近似的 设施。在非正式用法中,宿主 指以相同方式通过附录 D 与本规范接口的一组所有实现,例如所有 Web 浏览器的集合。宿主 通常是外部规范,例如 WHATWG HTML(https://html.spec.whatwg.org/ )。换言之,宿主定义的 设施通常在外部规范中进一步定义。
宿主钩子 是整体或部分由外部来源定义的抽象操作 。所有宿主钩子 都必须列在附录 D 中。宿主钩子 必须至少符合以下要求:
宿主定义的 设施,是指其定义无进一步限定地推迟给外部来源,并列在附录 D 中的设施。非宿主 的实现也可以为宿主定义的 设施提供定义。
宿主环境 是对所有宿主 定义设施的一组特定定义选择。宿主环境 通常包括一些对象或函数,它们允许作为全局对象 的宿主 定义属性来获取输入和提供输出。
本规范遵循始终使用最具体术语的编辑约定。例如,如果某设施是宿主定义的 ,就不应称其为实现定义的 。
宿主 和实现均可通过本文定义的语言类型、规范类型、抽象操作 、语法产生式、内在对象和内在符号与本规范接口。
4.3 ECMAScript 概述
以下是 ECMAScript 的非正式概述——并未描述该语言的所有部分。此概述不是标准正文的一部分。
ECMAScript 是基于对象的:基本语言和宿主 设施由对象提供,而 ECMAScript 程序是一组相互通信的对象。在 ECMAScript 中,对象 是零个或多个属性 的集合,每个属性都有决定该属性如何使用的特性 ——例如,当某属性的 Writable 特性被设置为 false 时,执行中的 ECMAScript 代码任何试图为该属性赋不同值的操作都会失败。属性是容器,可持有其他对象、原始值 或函数 。原始值是以下内置类型之一的成员:Undefined 、Null 、Boolean 、Number 、BigInt 、String 和 Symbol; 对象是内置类型 Object 的成员;函数是可调用对象。通过属性与对象关联的函数称为方法 。
ECMAScript 定义了一组内置对象 ,用于完善 ECMAScript 实体的定义。这些内置对象包括全局对象 ;对语言运行时语义 至关重要的对象,包括 Object、Function、Boolean、Symbol 和各种 Error 对象;表示和操纵数值的对象,包括 Math、Number 和 Date;文本处理对象 String 和 RegExp;作为值的索引集合的对象,包括 Array 和九种不同类型的 Typed Arrays,其元素均具有特定的数值数据表示;键控集合,包括 Map 和 Set 对象;支持结构化数据的对象,包括 JSON 对象、ArrayBuffer、SharedArrayBuffer 和 DataView;支持控制抽象的对象,包括生成器函数和 Promise 对象;以及反射对象,包括 Proxy 和 Reflect。
ECMAScript 还定义了一组内置运算符 。ECMAScript 运算符包括各种一元运算、乘性运算符、加性运算符、按位移位运算符、关系运算符、相等运算符、二元按位运算符、二元逻辑运算符、赋值运算符以及逗号运算符。
大型 ECMAScript 程序由模块 支持,模块允许将程序划分为多个语句和声明序列。每个模块显式标识其使用且需要由其他模块提供的声明,以及其哪些声明可供其他模块使用。
ECMAScript 语法有意类似 Java 语法。ECMAScript 语法较为宽松,以使其可作为易于使用的脚本语言。例如,变量不要求声明其类型,类型也不与属性关联,且已定义函数不要求其声明在文本上出现在对它们的调用之前。
4.3.1 对象
尽管 ECMAScript 包含 用于类定义的语法,但 ECMAScript 对象并不像 C++、Smalltalk 或 Java 中的对象那样从根本上基于类。相反,对象可以通过多种方式创建,包括通过字面量表示法,或通过构造函数 ;构造函数 创建对象,然后执行代码,通过为其属性赋初始值来初始化对象的全部或部分。每个构造函数 都是一个函数,并且具有名为 "prototype" 的属性,该属性用于实现基于原型的继承 和共享属性 。对象通过在 new 表达式中使用构造函数 来创建;例如,new Date(2009, 11) 创建一个新的 Date 对象。不使用 new 调用构造函数 会产生取决于该构造函数 的后果。例如,Date() 产生当前日期和时间的字符串表示,而不是对象。
由构造函数 创建的每个对象都有一个对其构造函数 的 "prototype" 属性值的隐式引用(称为该对象的原型 )。此外,原型可以具有对其原型的非 null 隐式引用,依此类推;这称为原型链 。当引用对象中的某个属性时,该引用指向原型链中第一个包含 该名称属性的对象中的该名称属性。换言之,首先检查直接提到的对象是否有这样的属性;如果该对象包含 该命名属性,这就是该引用所指的属性;如果该对象不包含 该命名属性,则接着检查该对象的原型;依此类推。
Figure 1: Object/Prototype Relationships
在基于类的面向对象语言中,一般来说,状态由实例承载,方法由类承载,而继承只继承结构和行为。在 ECMAScript 中,状态和方法由对象承载,而结构、行为和状态都会被继承。
所有不直接包含 其原型所包含 的某个特定属性的对象,都共享该属性及其值。图 1 说明了这一点:
CF 是一个构造函数 (同时也是一个对象)。使用 new 表达式创建了五个对象:cf1 、cf2 、cf3 、cf4 和 cf5 。这些对象各自都包含 名为 "q1" 和 "q2" 的属性。虚线表示隐式原型关系;因此,例如,cf3 的原型是 CFp 。构造函数 CF 自身具有两个属性,名为 "P1" 和 "P2" ,它们对 CFp 、cf1 、cf2 、cf3 、cf4 或 cf5 均不可见。CFp 中名为 "CFP1" 的属性由 cf1 、cf2 、cf3 、cf4 和 cf5 共享(但不由 CF 共享),CFp 的隐式原型链中任何不名为 "q1" 、"q2" 或 "CFP1" 的属性也是如此。注意,CF 与 CFp 之间没有隐式原型链接。
不同于大多数基于类的对象语言,可以通过向对象赋值来动态添加属性。也就是说,构造函数 不要求命名或赋值给所构造对象的全部或任何属性。在上图中,可以通过为 CFp 中的属性赋新值,为 cf1 、cf2 、cf3 、cf4 和 cf5 添加一个新的共享属性。
虽然 ECMAScript 对象并非内在地基于类,但基于构造函数 、原型对象和方法的常见模式来定义类似类的抽象通常很方便。ECMAScript 内置对象本身就遵循这种类似类的模式。从 ECMAScript 2015 开始,ECMAScript 语言包含 语法化的类定义,允许程序员简洁地定义符合内置对象所用同一类似类抽象模式的对象。
4.3.2 ECMAScript 的严格变体
ECMAScript 语言承认,某些语言用户可能希望限制他们对该语言中可用某些特性的使用。他们可能出于安全考虑、为避免他们认为易出错的特性、为获得增强的错误检查,或出于他们自行选择的其他原因而这样做。为支持这种可能性,ECMAScript 定义了该语言的严格变体。该语言的严格变体排除常规 ECMAScript 语言的某些特定句法和语义特性,并修改某些特性的详细语义。严格变体还指定了额外的错误条件:在非严格形式语言未指定为错误的情况下,必须通过抛出错误异常来报告这些条件。
ECMAScript 的严格变体通常称为该语言的严格模式 。严格模式的选择,以及 ECMAScript 严格模式语法和语义的使用,如 11.2.2 所述,是在各个 ECMAScript 源文本单元级别显式进行的。由于严格模式是在句法源文本单元级别选择的,因此严格模式只施加在该源文本单元内具有局部效果的限制。严格模式不限制或修改任何必须跨多个源文本单元一致运行的 ECMAScript 语义方面。一个完整的 ECMAScript 程序可以由严格模式和非严格模式 ECMAScript 源文本单元共同组成。在这种情况下,严格模式只在实际执行定义于严格模式源文本单元内的代码时适用。
为符合本规范,ECMAScript 实现必须实现本规范定义的完整、不受限制的 ECMAScript 语言以及 ECMAScript 语言的严格变体。此外,实现必须支持将不受限制和严格模式源文本单元组合为单个复合程序。
4.4 术语和定义
为本文档之目的,适用以下术语和定义。
4.4.1 implementation-approximated
实现近似的 设施整体或部分由外部来源定义,但在本规范中具有推荐的理想行为
4.4.2 implementation-defined
实现定义的 设施整体或部分由本规范的外部来源定义
4.4.3 host-defined
与 implementation-defined 相同
Note
4.4.4 type
如条款 6 中定义的数据值集合
4.4.5 primitive value
如条款 6 中定义的 Undefined、Null、Boolean、Number、BigInt、Symbol 或 String 类型 之一的成员
Note
4.4.6 object
Object 类型 的成员
Note
对象是属性的集合,并具有单个原型对象。该原型可以是 null 。
4.4.7 constructor
创建并初始化对象的函数对象
Note
构造函数 的 "prototype" 属性值是一个用于实现继承和共享属性的原型对象。
4.4.8 prototype
为其他对象提供共享属性的对象
Note
当构造函数 创建对象时,该对象为了求解属性引用,会隐式引用该构造函数 的 "prototype" 属性。构造函数 的 "prototype" 属性可由程序表达式 constructor .prototype 引用,而添加到对象原型的属性会通过继承由所有共享该原型的对象共享。或者,也可以使用 Object.create 内置函数创建一个具有显式指定原型的新对象。
4.4.9 ordinary object
对所有对象必须支持的基本内部方法具有默认行为的对象
4.4.10 exotic object
对一个或多个基本内部方法不具有默认行为的对象
Note
4.4.11 standard object
其语义由本规范定义的对象
4.4.12 built-in object
由 ECMAScript 实现指定并提供的对象
Note
标准内置对象在本规范中定义。ECMAScript 实现可以指定并提供额外种类的内置对象。
4.4.13 undefined value
当变量尚未被赋值时使用的原始值
4.4.14 Undefined type
唯一值为 undefined 值的类型
4.4.15 null value
表示有意缺少任何对象值的原始值
4.4.16 Null type
唯一值为 null 值的类型
4.4.17 Boolean value
Boolean 类型 的成员
Note
只有两个 Boolean 值,true 和 false 。
4.4.18 Boolean type
由原始值 true 和 false 组成的类型
4.4.19 Boolean object
Object 类型 的成员,是标准内置 Boolean 构造函数 的实例
Note
Boolean 对象通过在 new 表达式中使用 Boolean 构造函数 并提供 Boolean 值作为实参来创建。所得对象具有一个值为该 Boolean 值的内部槽。Boolean 对象可以被强制转换为 Boolean 值。
4.4.20 String value
作为零个或多个 16 位无符号整数值的有限 有序序列的原始值
Note
String 值是 String 类型 的成员。序列中的每个整数值通常表示 UTF-16 文本的单个 16 位单元。然而,除这些值必须是 16 位无符号整数外,ECMAScript 对这些值不施加任何限制或要求。
4.4.21 String type
所有可能 String 值的集合
4.4.22 String object
Object 类型 的成员,是标准内置 String 构造函数 的实例
Note
String 对象通过在 new 表达式中使用 String 构造函数 并提供 String 值作为实参来创建。所得对象具有一个值为该 String 值的内部槽。String 对象可以通过将 String 构造函数 作为函数调用而被强制转换为 String 值(22.1.1.1 )。
4.4.23 Number value
对应于双精度 64 位二进制格式 IEEE 754-2019 值的原始值
Note
4.4.24 Number type
所有可能 Number 值 的集合,包括 NaN (“not a number”)、+∞ 𝔽 (正无穷)和 -∞ 𝔽 (负无穷)
4.4.25 Number object
Object 类型 的成员,是标准内置 Number 构造函数 的实例
Note
Number 对象通过在 new 表达式中使用 Number 构造函数 并提供 Number 值 作为实参来创建。所得对象具有一个值为该 Number 值 的内部槽。Number 对象可以通过将 Number 构造函数 作为函数调用而被强制转换为 Number 值 (21.1.1.1 )。
4.4.26 Infinity
作为正无穷 Number 值 的 Number 值
4.4.27 NaN
作为 IEEE 754-2019 NaN(“not a number”)值的 Number 值
4.4.28 BigInt value
对应于任意精度整数值的原始值
4.4.29 BigInt type
所有可能 BigInt 值的集合
4.4.30 BigInt object
Object 类型 的成员,是标准内置 BigInt 构造函数 的实例
4.4.31 Symbol value
表示唯一的非 String Object 属性键 的原始值
4.4.32 Symbol type
所有可能 Symbol 值的集合
4.4.33 Symbol object
Object 类型 的成员,是标准内置 Symbol 构造函数 的实例
4.4.34 function
Object 类型 的成员,可以作为子例程被调用
Note
除其属性外,函数还包含 可执行代码和状态,它们决定函数在被调用时如何行为。函数的代码可以用 ECMAScript 编写,也可以不用 ECMAScript 编写。
4.4.35 built-in function
作为函数的内置对象
Note
内置函数的示例包括 parseInt 和 Math.exp。宿主 或实现可以提供本规范中未描述的额外内置函数。
4.4.36 built-in constructor
作为构造函数 的内置函数
Note
内置构造函数 的示例包括 Object 和 Function。宿主 或实现可以提供本规范中未描述的额外内置构造函数 。
4.4.37 property
对象中将键(String 值或 Symbol 值)与值关联起来的部分
Note
取决于属性的形式,该值可以直接表示为数据值(原始值、对象或函数对象 ),也可以间接由一对访问器函数表示。
4.4.38 method
作为属性值的函数
Note
当函数作为对象的方法被调用时,该对象会作为其 this 值传递给该函数。
4.4.39 built-in method
作为内置函数的方法
Note
标准内置方法在本规范中定义。宿主 或实现可以提供本规范中未描述的额外内置方法。
4.4.40 attribute
定义属性某些特征的内部值
4.4.41 own property
直接包含 在其对象中的属性
4.4.42 inherited property
对象的属性,其不是自有属性,而是该对象原型的属性(自有或继承)
4.5 本规范的组织
本规范其余部分组织如下:
条款 5 定义本规范通篇使用的记号约定。
条款 6 到 10 定义 ECMAScript 程序运行所在的执行环境。
条款 11 到 17 定义实际的 ECMAScript 编程语言,包括其句法编码以及所有语言特性的执行语义。
条款 18 到 28 定义 ECMAScript 标准库。它们包括 ECMAScript 程序执行时可供其使用的所有标准对象的定义。
条款 29 描述对 SharedArrayBuffer 支持的内存的访问以及 Atomics 对象方法的内存一致性模型。