翻译 ECMA-262 规范,也就是 ECMAScript 的规范的第四节 Overview,重新梳理 JS 中的一些基本概念,最后理解一下在 ECMAScript 中 property
和 attribute
的区别。
翻译
本章节包含 ECMAScript 语言的非规范性概述。
EcmaScript 是一种面向对象程序设计语言,用于在宿主环境中执行计算和操作计算对象。 这里定义的 ECMAScript 并不打算在计算上完全自我实现; 实际上,本规范中没有关于外部数据输入或计算结果输出的规定。 相反,预计 ECMAScript 程序的计算环境将不仅提供本规范中描述的对象和其他工具,而且还提供某些特定环境的对象,这些对象的描述和行为超出了本规范的范围,只是表明它们可能提供可以访问的特定属性和可以从 ECMAScript 程序调用的特定函数。
最初设计 ECMAScript 时是作为一个脚本语言,但现在已经被广泛用作多用途的编程语言。脚本语言时用来操作、定制和自动化现有系统工具的编程语言。 在这样的系统中,有用的功能已经可以通过用户界面实现,而脚本语言控制是一种将这种功能暴露给程序控制的机制。 通过这种方式,现有的系统被认为提供了一个由对象和工具组成的宿主环境,这就完成了脚本语言的功能。专业程序员和非专业程序员都可以使用脚本语言。
EcmaScript 最初被设计为一个 Web 脚本语言,提供一种机制来在浏览器中使 Web 页面更生动,并作为基于 Web 的客户机-服务器架构的一部分执行服务器计算。 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.
Web 脚本
Web 浏览器为客户端计算提供了 ECMAScript 宿主环境,例如,表示窗口、菜单、弹出窗口、对话框、文本区、锚、框架、历史记录、 cookies 和输入 / 输出的对象。 此外,宿主环境提供了一种方法来附加脚本代码的事件,如改变焦点,页面和图像加载,卸载,错误和中止,选择,表单提交和鼠标操作。 脚本代码出现在 HTML 中,显示的页面是用户界面元素以及固定和计算文本和图像的组合。 脚本代码是针对用户交互的,不需要主程序。
Web 服务器为服务器端计算提供了不同的宿主环境,包括表示请求、客户端和文件的对象,以及锁定和共享数据的机制。 通过同时使用浏览器端和服务器端脚本,可以在客户端和服务器之间分配计算,同时为 Web 应用程序提供定制的用户界面。
每个支持 ECMAScript 的 Web 浏览器和服务器都提供自己的完成 ECMAScript 执行的宿主环境。
ECMAScript 概述
下面是 ECMAScript 的一个非正式概述————并不是所有的部分都被描述了。 这个概述不是标准的一部分。
EcmaScript 是基于对象的: 基本语言和宿主工具由对象提供,ECMAScript 程序是一个通信对象集群。 在 ECMAScript 中,对象是由零个或多个 property 组成的集合,每个 property 都具有决定如何使用每个 property 的 attribute ——例如,当 property 的 Writable 属性设置为 false 时,任何已执行 ECMAScript 代码为属性分配不同值的尝试都将失败。 属性是容纳其他对象、基本类型值或函数的容器。 基本类型值是下列内置类型之一的成员: Undefined、 Null、 Boolean、 Number、 String 和 Symbol; 对象是内置类型 Object 的成员; 函数是可调用对象。函数通过一个叫方法的属性与对象联系起来。
Ecmascript 定义了一组内置对象,这些对象完善了 ECMAScript 实体的定义。 这些内置对象包括全局对象; 对语言语义有重要意义的对象,包括 Object、 Function、 Boolean、 Symbol 和各种 Error 对象; 表示和操作数值(包括 Math、 Number 和 Date)的对象; 文本处理对象 String 和 RegExp; 包括 Array 和 9 种不同类型的类型数组(其元素都具有特定的数值数据表示)的索引值集合对象; 包括 Map 和 Set 对象的键值对集合; 支持结构化数据(包括 JSON 对象、 ArrayBuffer、 sharedarbuffer 和 DataView)的对象; 支持抽象化控制(包括 generator 函数和 Promise 对象)的对象; 以及包括 Proxy 和 Reflect 对象在内的反射对象。
Ecmascript 还定义了一组内置操作符。 运算符包括各种一元运算符、乘法运算符、加法运算符、位移运算符、关系运算符、相等运算符、二元位运算符、二元逻辑运算符、赋值运算符和逗号运算符。
大型 ECMAScript 程序支持模块功能,这些模块允许程序被划分为多个语句和声明序列。 每个模块都明确指出它使用的声明需要由其他模块提供,以及哪些声明可供其他模块使用。
语法有意地模仿 Java 语法。 但 Ecmascript 语法比较宽松,可以作为一个易于使用的脚本语言。 例如,变量不需要声明其类型,属性也不需要与类型关联,已定义的函数不需要在调用它们之前以文本形式显示其声明。
对象
尽管 ECMAScript 包含定义类的语法,但是 ECMAScript 对象并不像 c++ 、Smalltalk 或 Java 中的对象那样基于类。 而是可以通过各种方式创建对象,包括通过文字符号或通过构造函数创建对象,然后执行代码,通过为其属性分配初始值来初始化所有或部分对象。 每个构造函数都有一个名为“ prototype”的属性,用于实现基于原型的继承和共享属性。 对象是通过在 new 表达式中使用构造函数创建的; 例如,new Date (2009,11)创建一个新的 Date 对象。 在不使用 new 的情况下调用构造函数会产生依赖于构造函数的结果。 例如,Date ()生成当前日期和时间的字符串表示形式,而不是对象。
构造函数创建的每个对象都对其构造函数的“prototype”属性的值有一个隐式引用(称为对象的 prototype)。 此外,一个原型可能对其自身的原型有一个非空的隐式引用,以此类推,这就是所谓的原型链。当引用对象中的属性时,该引用指向该原型链中包含属性的第一个对象中的该名称属性。 换句话说,首先检查当前对象是否具有这样的属性; 如果该对象包含指定的属性,那就是引用所指向的属性; 如果该对象不包含指定的属性,则接下来检查该对象的原型,以此类推。
一般情况下,在基于类的面向对象语言中,状态由实例承载,方法由类承载,只继承结构和行为。 在 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 之间没有隐式原型链。
与大多数基于类的对象语言不同,属性可以通过为对象赋值来动态地添加到对象中。 也就是说,构造函数不需要为所构造的对象的所有或任何属性命名或赋值。 在上面的图中,可以为 cf1、 cf2、 cf3、 cf4 和 cf5 添加一个新的共享属性,方法就是是为 CFp 中的属性分配一个新值。
虽然 ECMAScript 对象本质上并不是基于类的,但是基于构造函数、原型对象和方法的公共模式来定义抽象类通常比较方便。 Ecmascript 内置对象本身遵循类似的模式。 从 ECMAScript 2015 开始,ECMAScript 语言包含了语法 class 定义,允许程序员精确定义符合内置对象所使用的类似抽象类模式的对象。
Ecmascript 的严格模式
Ecmascript 语言认识到了一些用户可能希望能够限制一些特性。 他们这样希望可能是出于安全考虑,或者避免他们认为某些特性容易出错,或者为了增强的错误检查,或者出于他们选择的其他原因。 为了支持这种限制,ECMAScript 定义了该语言的一个严格变体。 该语言的严格变体排除了常规 ECMAScript 语言的一些特定的语法和语义特征,并修改了一些特征的详细语义。 严格变体还指定了额外的错误条件,抛出错误异常来报告。
Ecmascript 的严格变体通常被称为语言的严格模式。 严格模式的选择和严格模式的语法和语义的使用是在各个 ECMAScript 源文本单元级别上显式地进行的。 由于严格模式是在语法源文本单元级别选择的,因此严格模式只该源文本单元施加局部限制。在多个源文本单元之间共同运行 ECMAScript 时, 严格模式不在任何方面限制或修改其他单元的语义。 一个完整的 ECMAScript 程序可以由严格模式和非严格模式的 ECMAScript 源文本单元共同组成。 在这种情况下,严格模式仅在执行定义了严格模式的源文本单元的代码时应用。
为了符合这个规范,ECMAScript 实现时必须同时实现不受限制的 ECMAScript 语言和 ECMAScript 语言的严格变体。 此外,实现必须支持将不受限制和严格模式的源文本单元组合到单个复合程序中。
术语和定义
就本文件而言,适用以下术语和定义。
type
本规范种第 6 节中定义的数据集合。
primitive value
第 6 节中 Undefined、 Null、 Boolean、 Number、 Symbol 或 String 类型之一的成员。
object
Object 类型的成员。
注意:对象是属性的集合,并且只有一个原型对象。原型可能是空值。
constructor
创建和初始化对象的函数对象。
注意:构造函数的原型属性的值是用于实现继承和共享属性的原型对象。
prototype
为其他对象提供共享属性的对象
注意:当构造函数创建一个对象时,该对象隐式引用构造函数的原型属性,用来解析属性。 构造函数的原型属性可以被程序表达式 constructor.prototype 引用,添加到对象原型的属性通过继承的方式被共享原型的所有对象共享。 或者可以使用 Object.create 内置函数显式的指定的原型来创建新对象。
ordinary object
该对象具有必须由所有对象支持的基本内部方法的默认表现。
exotic object
该对象不完全具备所有基本内部方法的默认表现。
standard object
语义由本规范定义的对象。
built-in object
由 ECMAScript 的实现来指定和提供对象。
undefined value
当变量没有被赋值时使用的原始值。
Undefined type
该类型唯一的值是 undefined。
null value
表示任何对象值的故意缺失的原始值。
Null type
类型,其唯一值为 null
Boolean value
Boolean 类型的成员。
注意:只有两个 Boolean 类型的值,true 和 false。
Boolean type
类型,由原始值 true 和 false 组成。
Boolean object
Object 类型的成员,它是标准内置 Boolean 构造函数的实例
注意:在 new 表达式中使用 Boolean 构造函数创建 Boolean 对象,并提供一个 Boolean 值作为参数。 结果对象有一个内部槽,其值为 Boolean 值。 Boolean 对象可以强制为 Boolean 值。
String value
原始值,是由任意个 16 位无符号整数值组成的有限有序序列。
注意:String 值是 String 类型的成员。 序列中的每个整数值通常表示单个 16 位 UTF-16 文本单元。 但是,ECMAScript 没有对这些值设置任何限制或要求,除非它们必须是 16 位无符号整数。
String type
所有可能的字符串值的集合
String object
Object 类型的成员,它是标准内置 String 构造函数的实例
注意:通过在 new 表达式中使用 String 构造函数创建 String 对象,并提供 String 值作为参数。 结果对象有一个内部槽,其值为 String 值。 通过像 function 章节那样调用 String 构造函数 ,可以将 String 对象强制为 String 值。
Number value
与双精度 64 位二进制格式 IEEE 754-2008 值对应的原始值
注意:Number 值是 Number 类型的成员,是数字的直接表示形式。
Number type
所有可能的 Number 值的集合,包括特殊的“ not-a-Number”(NaN)值、正无穷大和负无穷大。
Number object
Object 类型的成员,它是标准内置 Number 构造函数的实例
注意:在 new 表达式中使用 Number 构造函数创建 Number 对象,并提供一个数值作为参数。 结果对象具有一个内部槽,其值为数字值。 通过像 function 章节那样调用 Number 构造函数 ,可以将 Number 对象强制转换为一个数值。
Infinity
正无穷大的数值
NaN
是 IEEE 754-2008 中“Not-a-Number”值的数字值。
Symbol value
表示唯一的非字符串的 Object 属性键的原始值。
Symbol type
所有可能的 Symbol 值的集合
Symbol object
Object 类型的成员,该成员是标准内置 Symbol 构造函数的实例。
function
可以作为子程序调用的 Object 类型的成员。
注意:除了属性之外,函数还包含可执行代码和状态,这些代码和状态决定了函数被调用时的行为。 函数的代码不一定是用 ECMAScript 编写的。
built-in function
该函数是一个内置对象。
注意:内置函数的示例包括 parseInt 和 Math.exp。 实现时可以提供本规范中没有描述的与实现相关的内置函数。
property
对象的一部分,具有关联的键(String 值或 Symbol 值)和值。
注意:根据 property 的形式,值可以直接表示为数据值(原始值、对象或函数对象) ,也可以通过一对访问器函数间接表示。
method
是一个函数,这个函数也是是 property 的值。
注意:当一个函数作为一个对象的方法被调用时,这个对象作为 this 值传递给函数。
built-in method
方法,是一个内置函数。
注意:本规范定义了标准的内置方法,ECMAScript 实现时可以指定并提供其他内置方法。
attribute
internal value that defines some characteristic of a property
内部值,定义 一个 property 的某些特征。
own property
直接包含在其对象中的属性。
inherited property
对象的属性,但是不是对象本身的属性,而是对象原型的属性(自身的或继承的)。
本规范的结构
本规范的剩余部分结构如下:
第 5 条定义了整个规范中使用的符号约定。
6-9 条定义 操作 ECMAScript 程序的执行环境。
10-16 条定义了实际的 ECMAScript 编程语言,包括它的语法编码和所有语言特性的执行语义。
17-26 条定义 ECMAScript 标准库。 它们包括所有标准对象的定义,这些对象可供 ECMAScript 程序在执行时使用。
第 27 条描述了支持 SharedArrayBuffer 内存访问的内存一致性模型和 Atomics 对象的方法。
总结
在本节中有一句话,这句话中同时出现了 property
和 attribute
,都可以翻译为“属性
”:
In ECMAScript, an object is a collection of zero or more
properties
each withattributes
that determine how eachproperty
can be used—for example, when the Writableattribute
for aproperty
is set to false, any attempt by executed ECMAScript code to assign a different value to theproperty
fails.
翻译:
在 ECMAScript 中,对象是由零个或多个
property
组成的集合,每个property
都具有决定如何使用每个property
的attribute
——例如,当property
的Writable
attribute
设置为false
时,任何为property
分配不同值的 ECMAScript 代码执行的尝试都将失败。
再看规范中的定义:
property
:
对象的一部分,具有关联的键(String 值或 Symbol 值)和值。
注意:根据 property 的形式,值可以直接表示为数据值(原始值、对象或函数对象) ,也可以通过一对访问器函数间接表示。
attribute
:
内部值,定义 一个 property 的某些特征。
综合起来,我的理解是 property
是一个对象中的键值对,而 attribute
则是给该 property
设置的一些属性,比如 configurable
或 writable
之类。举个例子:
1 | Object.defineProperty(obj, 'name', { |
此时 property
应该是 obj
中的 name
键值对,而 attribute
是 writable
键值对,用来设置 name
键值对不可写。