# 概览

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

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

ECMAScript 最初被设计成一个 Web 脚本语言,提供了一种机制来活跃浏览器中的 Web 页面,并作为基于 Web 的客户机-服务器体系结构的一部分执行服务器计算。ECMAScript 现在用于为各种主机环境提供核心脚本功能。因此,除了任何特定的主机环境之外,核心语言都是在这个文档中指定的。

ECMAScript 的使用已经超越了简单的脚本,它现在用于许多不同环境和规模中的各种编程任务。随着 ECMAScript 使用的扩展,它所提供的特性和设施也随之扩展。ECmascript 现在是一个功能齐全的通用编程语言。

# Web 浏览器和服务器

Web 浏览器为客户端计算提供 ECMAScript 主机环境,例如,包括表示窗口、菜单、弹出窗口、对话框、文本区域、锚点、框架、历史记录、 cookie 和输入/输出的对象。此外,宿主环境还提供了将脚本代码附加到事件的方法,如焦点更改、页面和图像加载、卸载、错误和中止、选择、表单提交和鼠标操作。脚本代码出现在 HTML 中,显示的页面是用户界面元素以及固定和计算的文本和图像的组合。脚本代码是对用户交互的反应,并且不需要主程序。

Web 服务器为服务器端计算提供了不同的主机环境,包括表示请求、客户端和文件的对象,以及锁定和共享数据的机制。通过同时使用浏览器端和服务器端脚本,可以在客户端和服务器端之间分配计算,同时为网络应用程序提供定制的用户界面。

每个支持 ECMAScript 的 Web 浏览器和服务器都提供自己的主机环境,完成 ECMAScript 执行环境。

# 主机和实现

为了帮助将 ECMAScript 集成到主机环境中,本规范将某些设施(例如,抽象操作)的定义推迟到本规范之外的一个源中,不管是全部还是部分。编辑上,本规范区分了以下类型的延迟。

执行是一种外部来源,进一步界定了附件 D 所列举的设施或标明为执行定义或执行近似的设施。在非正式用法中,实现指的是一个具体的工件,例如一个特定的 Web 浏览器。

实现定义的工具是将其定义推迟到外部来源而没有进一步限定的工具。这个规范没有为特定的行为提出任何建议,符合规范的实现可以在这个规范提出的约束范围内自由选择任何行为。

一个近似于实现的工具是将其定义推迟到外部来源,同时推荐一个理想的行为。虽然符合规范的实现可以自由地选择本规范提出的约束内的任何行为,但是鼓励它们努力接近理想状态。一些数学运算,比如 Math.exp,是近似实现的。

东道国是进一步界定附件 D 所列设施的外部来源,但不进一步界定其他实施界定的或与实施相近的设施。在非正式使用中,宿主指的是所有实现的集合,例如所有 Web 浏览器的集合,它们通过附件 D 以相同的方式与本规范接口。主机通常是一个外部规范,比如 WHATWG HTML ( https://HTML.spec.WHATWG.org/)。换句话说,主机定义的设施通常在外部规范中进一步定义。

主机钩子是一种抽象操作,由外部源全部或部分定义。所有主机挂钩必须在附件 D 中列出。主机挂钩必须至少符合以下要求:

它必须返回正常完成或抛出完成。

东道国确定的设施是指在没有进一步限定的情况下将其定义推迟到外部来源并列入附件 D 的设施。

主机环境是所有主机定义设施的特定定义选择。宿主环境通常包括允许获取输入并将输出作为全局对象的宿主定义属性提供的对象或函数。

本规范遵循总是使用最具体术语的编辑惯例。例如,如果一个工具是主机定义的,那么它就不应该被称为实现定义的。

主机和实现都可以通过本文定义的语言类型、规范类型、抽象操作、语法产生、内部对象和内部符号与本规范接口。

# ECMAScript 概览

以下是对 ECMAScript 的非正式概述ーー并非对该语言的所有部分都进行了描述。这个概述不是标准的一部分。

ECMAScript 是基于对象的: 基本语言和主机设施由对象提供,ECMAScript 程序是通信对象的集群。在 ECMAScript 中,对象是由零个或多个属性组成的集合,每个属性都具有决定如何使用每个属性的属性ーー例如,当一个属性的 Writable 属性设置为 false 时,执行的 ECMAScript 代码为该属性分配不同值的任何尝试都会失败。属性是容纳其他对象、基元值或函数的容器。基元值是下列内置类型之一的成员: 未定义类型、空类型、布尔类型、数字类型、 BigInt 类型、字符串类型和符号类型; 对象是内置类型 Object 的成员; 函数是可调用对象。通过属性与对象关联的函数称为方法。

ECMAScript 定义了内置对象的集合,这些对象完善了 ECMAScript 实体的定义。这些内置对象包括全局对象; 对语言的运行时语义至关重要的对象,包括 Object、 Function、 Boolean、 Sign 和各种 Error 对象; 表示和操作数值的对象,包括 Math、 Number 和 Date; 文本处理对象 String 和 RegExp; 索引值集合的对象,包括 Array 和9种不同类型的 Type Array,它们的元素都有特定的数值表示; 键控集合,包括 Map 和 Set 对象; 支持结构化数据的对象,包括 JSON 对象、 ArrayBuffer、 SharedArrayBuffer 和 DataView; 支持控制抽象的对象,包括生成器函数和承诺对象; 以及包括 Proxy 和 Refect 在内的反射对象。

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

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

ECMAScript 语法故意类似于 Java 语法。ECMAScript 语法更加宽松,使其成为一个易于使用的脚本语言。例如,变量不需要声明它的类型,也不需要与属性关联的类型,定义的函数不需要在调用它们之前以文本形式显示它们的声明。

# 对象

尽管 ECMAScript 包含了类定义的语法,但 ECMAScript 对象并不像 C + + 、 Smalltalk 或 Java 中的对象那样基于类。相反,可以通过各种方式创建对象,包括通过文本符号或通过构造函数创建对象,然后执行代码,通过为其属性分配初始值来初始化全部或部分对象。每个构造函数都有一个名为“原型”的属性,用于实现基于原型的继承和共享属性。对象是通过在新表达式中使用构造函数创建的; 例如,new Date (2009,11)创建一个新 Date 对象。不使用 new 调用构造函数的后果取决于构造函数。例如,Date ()生成当前日期和时间的字符串表示形式,而不是对象。

构造函数创建的每个对象都有一个对其构造函数的“原型”属性值的隐式引用(称为对象的原型)。此外,原型可能对其原型有非空的隐式引用,等等; 这称为原型链。当对对象中的属性进行引用时,该引用指的是原型链中包含该名称的属性的第一个对象中的该名称的属性。换句话说,首先检查直接提到的对象是否具有这样的属性; 如果该对象包含命名属性,即引用所引用的属性; 如果该对象不包含命名属性,则接下来检查该对象的原型; 以此类推。

TIP

TODO

在基于类的面向对象语言中,一般情况下,状态由实例承载,方法由类承载,继承只是结构和行为的继承。在 ECMAScript 中,状态和方法由对象承载,而结构、行为和状态都是继承的。

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

CF 是一个构造函数(也是一个对象)。使用新表达式创建了五个对象: 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 语言包含语法类定义,允许程序员简明地定义符合内置对象所使用的类似于类的抽象模式的对象。

# 严格模式

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

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

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

# 术语及定义

对于本文档,应用以下术语和定义。

# 近似实现

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

# 实现定义

实现定义的工具全部或部分由本规范的外部源定义

# 类型

类型进一步细分为ECMAScript 语言类型和规格类型

# 对象

对象在逻辑上是属性的集合。每个属性要么是数据属性,要么是访问器属性

# 原始值

undefined,null,布尔值,数字,BitInt,Symbol,字符串

# 构造器

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

# 原型

一个对象,该对象为其他对象提供共享属性

# 普通对象

对象,该对象具有所有对象都必须支持的基本内部方法的默认行为

# 外来对象

对象,该对象不具有一个或多个基本内部方法的默认行为

TIP

在 ECMAScript 中,一个对象要么是普通对象,要么是外来对象。

# 标准对象

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

# 内置对象

由 ECMAScript 实现指定和提供的对象

TIP

标准的内置对象在此规范中定义。ECMAScript 实现可以指定并提供其他类型的内置对象。内置构造函数是一个内置对象,也是一个构造函数。

# 内置函数

作为函数的内置对象

TIP

内置函数的示例包括 parseInt 和 Math.exp。主机或实现可以提供本规范未描述的其他内置函数。

# 自身属性

对象直接包含的属性

# 继承属性

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

# 本规范的结构

本规范的其余部分组织如下:

第5条定义了整个规范中使用的符号约定。

子句6到10定义了 ECMAScript 程序在其中运行的执行环境。

子句11到17定义了实际的 ECMAScript 编程语言,包括其语法编码和所有语言特性的执行语义。

子句18到28定义了 ECMAScript 标准库。它们包括执行 ECMAScript 程序时可以使用的所有标准对象的定义。

第29条描述了访问 SharedarrayBuffer 支持的内存的内存内存一致性模型和 Atomics 对象的方法。