ECMAScript 2015 数据类型之外部数据类型
简述
这里要介绍的数据类型分为两类:
-
ECMAScript Language Type (外部数据类型,开发人员可以直接使用)
-
ECMAScript Specific Type (内部数据类型,开发人员无法直接使用)
我们今天讲述的是 ECMAScript Language Type (外部数据类型)
简写:
-
the notation “Type(x)” is used as shorthand for “the type of x” where “type” refers to the ECMAScript language and specification types. 简写 Type(x) 代表变量x 的ECMAScript数据类型
-
When the term “empty” is used as if it was naming a value, it is equivalent to saying “no value of any type”. 术语 empty 表示没有数据类型
ECMAScript Language Types
An ECMAScript language type corresponds to values that are directly manipulated by an ECMAScript programmer using the ECMAScript language. The ECMAScript language types are Undefined, Null, Boolean, String, Symbol, Number, and Object. An ECMAScript language value is a value that is characterized by an ECMAScript language type.
我们在ECMAScript语言程序中使用的数据值都有对应的ECMAScript数据类型,它们包括:Undefined, Null, Boolean, String, Symbol, Number, Object。
ECMAScript数据类型是数据值的分类。
The Undefined Type
只有一个值 undefined,一个未赋值的变量,其值为undefined
The Null Type
只有一个值 null , 表示一个空指针,一般用来释放对象内存。
The String Type
The String type is the set of all ordered sequences of zero or more 16-bit unsigned integer values (“elements”) up to a maximum length of 2^53-1 elements.
字符串类型是16-bit 无符号整数的有序序列,其最大元素个数为2^53-1
The String type is generally used to represent textual data in a running ECMAScript program, in which case each element in the String is treated as a UTF-16 code unit value.
字符串类型用来表示文本数据,每个元素被认为是一个UTF-16编码(对UTF-16不了解的同学可以看一下这篇文章)的数据单元。
字符串的每个元素在序列中占据一个位置,这些位置使用自然数(非负整数)进行排序。字符串的长度是元素的个数。空字符串的长度为0,它不包含任何元素。
The Symbol Type
Symbol类型的出现是为了表示对象的key(键)。
每一个Symbol类型的数据都是唯一的且不可更改。
Each Symbol value immutably holds an associated value called [[ Description ]] that is either undefined or a String value.
每一个Symbol类型的数据拥有一个内部不可变属性 [[ Description ]] 它的值为 undefined 或者 字符串(简单理解为对Symbol类型数据的含义描述)。
Well-Known Symbols (内置符号)
Well-known symbols are built-in Symbol values that are explicitly referenced by algorithms of this specification. They are typically used as the keys of properties whose values serve as extension points of a specification algorithm. Unless otherwise specified, well-known symbols values are shared by all Code Realms。
Well-Known Symbols 是一些内置的Symbol值,它们会被es6规范中的算法引用。一般来说,Well-Known Symbols是用来代表属性的键,这些属性的值扮演着es6规范算法扩展点的作用(简单理解为es6想把一些内部行为开放给开发者,这些Well-Known Symbol属性则是这些内部行为的承载者)。
由于这些 Well-Known Symbols 是es6开放出来的,他对之前的一些语法是无效的,例如 之前的函数定义上无法修改@@hasInstance,只能在类的写法上有效。
规范中的 Well-Known Symbol 使用形式符号 @@name 代表,其中name表示下列表格之一:
| Specification Name | [[ Description ]] | Value and Purpose |
|---|---|---|
| @@hasInstance | "Symbol.hasInstance" | A method that determines if a constructor object recognizes an object as one of the constructor’s instances. Called by the semantics of the instanceof operator. 操作符 instanceof 调用的方法,用来判断一个对象是否为某个构造器的实例,可动态修改 |
| @@isConcatSpreadable | "Symbol.isConcatSpreadable" | A Boolean valued property that if true indicates that an object should be flattened to its array elements by Array.prototype.concat. 数组或类数组对象在调用Array.prototype.concat方法时的可展开配置,数组对象默认展开,类数组对象默认不展开,可动态修改 |
| @@iterator | "Symbol.iterator" | A method that returns the default Iterator for an object. Called by the semantics of the for-of statement. 操作符 for of会调用的方法,返回一个迭代器,用于可迭代对象,可动态修改 |
| @@match | "Symbol.match" | A regular expression method that matches the regular expression against a string. Called by the String.prototype.match method.String.prototype.match调用的方法,用于正则判断,修改的是正则对象实例,可动态修改 |
| @@replace | "Symbol.replace" | A regular expression method that replaces matched substrings of a string. Called by the String.prototype.replace method.String.prototype.replace调用的方法,用于字符串处理,修改的是正则对象实例,可动态修改 |
| @@search | "Symbol.search" | A regular expression method that returns the index within a string that matches the regular expression. Called by the String.prototype.search method.String.prototype.search调用的方法,用于字符串查找,修改的是正则对象实例,可动态修改 |
| @@species | "Symbol.species" | A function valued property that is the constructor function that is used to create derived objects.指定派生对象的构造器,它是一个访问器属性(getter),属性允许子类覆盖对象的默认构造函数 |
| @@split | "Symbol.split" | A regular expression method that splits a string at the indices that match the regular expression. Called by the String.prototype.split method. |
| @@toPrimitive | "Symbol.toPrimitive" | A method that converts an object to a corresponding primitive value. Called by the ToPrimitive abstract operation.ToPrimitive 抽象操作会调用的方法,用于将对象转化为原始值 |
| @@toStringTag | "Symbol.toStringTag" | A String valued property that is used in the creation of the default string description of an object. Accessed by the built-in method Object.prototype.toString.Object.prototype.toString调用的方法,它是一个对象的字符串描述 |
| @@unscopables | "Symbol.unscopables" | An object valued property whose own property names are property names that are excluded from the with environment bindings of the associated object.用于with操作符,指定某些属性不在with指定作用域中 |
The Number Type
The Number type has exactly 18437736874454810627 (that is, 264^253+3) values, representing the double-precision 64-bit format IEEE 754-2008 values as specified in the IEEE Standard for Binary Floating-Point Arithmetic, except that the 9007199254740990 (that is, 253^2) distinct “Not-a-Number” values of the IEEE Standard are represented in ECMAScript as a single special NaN value. (Note that the NaN value is produced by the program expression NaN.)
数字类型值遵循IEEE 754-2008标准中的64 bit 双精度数值。IEEE 754-2008中的“Not-a-Number”值在ECMAScript中的具体实现是NaN。
数字类型中有两个特殊值 positive Infinity 和 negative Infinity。
另外,存在positive zero 和 negative zero。
关于数值比较,参考 JavaScript中的相等性判断
The Object Type
An Object is logically a collection of properties. Each property is either a data property, or an accessor property:
- A data property associates a key value with an ECMAScript language value and a set of Boolean attributes.
- An accessor property associates a key value with one or two accessor functions, and a set of Boolean attributes. The accessor functions are used to store or retrieve an ECMAScript language value that is associated with the property.
对象是一个属性的集合。属性有两种,数据属性和访问器属性:
- 数据属性 属性与 ECMAScript language value相关联 并有其他的 布尔值控制其行为
- 访问器属性 属性与 一个或两个 访问器函数 相关联 并有其他的布尔值控制其行为
Properties are identified using key values. A property key value is either an ECMAScript String value or a Symbol value.
属性使用 key 进行标识。属性的 key 有两种: String value 或者 Symbol value
属性的键是用来访问属性值的。有两种属性访问操作:get 和 set,顾名思义,get 表示 检索属性值 ,set 表示 设置属性值。当然,之前说过了对象的继承机制,这里的访问操作不单单指的是对象自身的属性,也包括从原型链中继承的属性。
属性的特性 Property Attributes
属性的特性用来描述属性的表现。
- 数据属性的特性:
| Attribute Name | Value Domain | Description |
|---|---|---|
| [[Value]] | Any ECMAScript language type | The value retrieved by a get access of the property. |
| [[Writable]] | Boolean | If false, attempts by ECMAScript code to change the property’s [[ Value ]] attribute using [[ Set ]] will not succeed. |
| [[Enumerable]] | Boolean | If true, the property will be enumerated by a for-in enumeration . Otherwise, the property is said to be non-enumerable. |
| [[Configurable]] | Boolean | If false, attempts to delete the property, change the property to be an accessor property, or change its attributes (other than [[[ Value ]], or changing [[ Writable]] to false) will fail. |
- 访问器属性的特性:
| Attribute Name | Value Domain | Description |
|---|---|---|
| [[Get]] | Object or Undefined | If the value is an Object it must be a function object. The function’s [[Call]] internal method (Table 6) is called with an empty arguments list to retrieve the property value each time a get access of the property is performed. |
| [[Set]] | Object or Undefined | If the value is an Object it must be a function object. The function’s [[Call]] internal method (Table 6) is called with an arguments list containing the assigned value as its sole argument each time a set access of the property is performed. The effect of a property's [[Set]] internal method may, but is not required to, have an effect on the value returned by subsequent calls to the property's [[Get]] internal method. |
| [[Enumerable]] | Boolean | If true, the property is to be enumerated by a for-in enumeration . Otherwise, the property is said to be non-enumerable. |
| [[Configurable]] | Boolean | If false, attempts to delete the property, change the property to be a data property, or change its attributes will fail. |
If the initial values of a property’s attributes are not explicitly specified by this specification, the default value defined 默认取值:
| Attribute Name | Default Value |
|---|---|
| [[Value]] | undefined |
| [[Get]] | undefined |
| [[Set]] | undefined |
| [[Writable]] | false |
| [[Enumerable]] | false |
| [[Configurable]] | false |
对象的内部方法和内部插槽 Object Internal Methods and Internal Slots
内部方法:
对象的实际语义表现是由规范中的一些算法控制的,这些算法称为内部方法。这些算法并不是 ECMAScript language 的一部分(意思是这些内部方法并不对外,它是JS引擎内部使用的,开发人员无法直接访问)。(我们在这里讨论这些内部方法,目的是为了更好的了解ECMAScript的运行机制,这属于高级内容,如果你是刚入门JS,那这些内容可以先跳过。)
内部方法具有多态的特性。这意味着,不同的对象对于同一个内部方法,其表现(执行的算法)可能是不同的。调用内部方法的实际对象称为调用的目标(target)。运行时过程中,如果出现对象调用ECMAScript实现不支持的内部方法时,则抛出TypeError。
内部插槽:
Internal slots correspond to internal state that is associated with objects and used by various ECMAScript specification algorithms.Internal slots are not object properties and they are not inherited. Depending upon the specific internal slot specification, such state may consist of values of any ECMAScript language type or of specific ECMAScript specification type values.Unless explicitly specified otherwise, internal slots are allocated as part of the process of creating an object and may not be dynamically added to an object. Unless specified otherwise, the initial value of an internal slot is the value undefined. Various algorithms within this specification create objects that have internal slots. However, the ECMAScript language provides no direct way to associate internal slots with an object.
内部插槽是与内部状态相关联的,这些内部状态会在对象操作中的一些内部算法中用到。内部插槽并不是对象属性并且他们也不能继承。这些内部状态可能是ECMAScript language type,也可能是 ECMAScript specification type 值。除非特别说明,内部插槽是作为对象生成的一部分存在的,它不能动态添加到对象上。除非特别说明,内部插槽的值为undefined。ECMAScript language没有提供直接操作关联到对象内部插槽的方法。
内部方法和内部插槽使用 [[ ]] 标记。
规范中定义的关键内部方法: Every object must have algorithms for all of the essential internal methods. However, all objects do not necessarily use the same algorithms for those methods.
表5 关键内部方法
下面表格介绍 关键内部方法的 输入---输出、定义、以及所有对象都应该遵循的条约。
Definitions:
- The target of an internal method is the object upon which the internal method is called.
- A target is non-extensible if it has been observed to return false from its [[IsExtensible]] internal method, or true from its [[PreventExtensions]] internal method.
- A non-existent property is a property that does not exist as an own property on a non-extensible target.
- All references to SameValue are according to the definition of SameValue algorithm specified in 7.2.9.
[[GetPrototypeOf]]
()=>Object|Null
Determine the object that provides inherited properties for this object. A null value indicates that there are no inherited properties.
● The Type of the return value must be either Object or Null. ● If target is non-extensible, and [[GetPrototypeOf]] returns a value v, then any future calls to [[GetPrototypeOf]] should return the SameValue as v. NOTE 1 An object’s prototype chain should have finite length (that is, starting from any object, recursively applying the [[GetPrototypeOf]] internal method to its result should eventually lead to the value null). However, this requirement is not enforceable as an object level invariant if the prototype chain includes any exotic objects that do not use the ordinary object definition of [[GetPrototypeOf]]. Such a circular prototype chain may result in infinite loops when accessing object properties.
[[SetPrototypeOf]]
(Object|Null)=>Boolean
Associate this object with another object that provides inherited properties. Passing null indicates that there are no inherited properties. Returns true indicating that the operation was completed successfully or false indicating that the operation was not successful.
● The Type of the return value must be Boolean. ● If target is non-extensible, [[SetPrototypeOf]] must return false, unless V is the SameValue as the target’s observed [[GetPrototypeOf]] value.
[[IsExtensible]]
()=>Boolean
Determine whether it is permitted to add additional properties to this object.
[[PreventExtensions]]
()=>Boolean
Control whether new properties may be added to this object. Returns true if the operation was successful or false if the operation was unsuccessful.
● The Type of the return value must be Boolean. ● If [[PreventExtensions]] returns true, all future calls to [[IsExtensible]] on the target must return false and the target is now considered non-extensible.
[[GetOwnProperty]]
(propertyKey) → Undefined | Property Descriptor
Return a Property Descriptor for the own property of this object whose key is propertyKey, or undefined if no such property exists.
● The Type of the return value must be either Property Descriptor or Undefined. ● If the Type of the return value is Property Descriptor, the return value must be a complete property descriptor (see 6.2.4.6). ● If a property P is described as a data property with Desc.[[Value]] equal to v and Desc.[[Writable]] and Desc.[[Configurable]] are both false, then the SameValue must be returned for the Desc.[[Value]] attribute of the property on all future calls to [[GetOwnProperty]] ( P ). ● If P’s attributes other than [[Writable]] may change over time or if the property might disappear, then P’s [[Configurable]] attribute must be true. ● If the [[Writable]] attribute may change from false to true, then the [[Configurable]] attribute must be true. ● If the target is non-extensible and P is non-existent, then all future calls to [[GetOwnProperty]] (P) on the target must describe P as non-existent (i.e. [[GetOwnProperty]] (P) must return undefined).
NOTE 2 As a consequence of the third invariant, if a property is described as a data property and it may return different values over time, then either or both of the Desc.[[Writable]] and Desc.[[Configurable]] attributes must be true even if no mechanism to change the value is exposed via the other internal methods.
[[HasProperty]]
(propertyKey) → Boolean
Return a Boolean value indicating whether this object already has either an own or inherited property whose key is propertyKey.
● The Type of the return value must be Boolean. ● If P was previously observed as a non-configurable data or accessor own property of the target, [[HasProperty]] must return true.
[[Get]]
(propertyKey, Receiver) → any
Return the value of the property whose key is propertyKey from this object. If any ECMAScript code must be executed to retrieve the property value, Receiver is used as the this value when evaluating the code.
● If P was previously observed as a non-configurable, non-writable own data property of the target with value v, then [[Get]] must return the SameValue. ● If P was previously observed as a non-configurable own accessor property of the target whose [[Get]] attribute is undefined, the [[Get]] operation must return undefined.
[[Set]]
(propertyKey,value, Receiver) → Boolean
Set the value of the property whose key is propertyKey to value. If any ECMAScript code must be executed to set the property value, Receiver is used as the this value when evaluating the code. Returns true if the property value was set or false if it could not be set.
● The Type of the return value must be Boolean. ● If P was previously observed as a non-configurable, non-writable own data property of the target, then [[Set]] must return false unless V is the SameValue as P’s [[Value]] attribute. ● If P was previously observed as a non-configurable own accessor property of the target whose [[Set]] attribute is undefined, the [[Set]] operation must return false.
[[Delete]]
(propertyKey) → Boolean
Remove the own property whose key is propertyKey from this object . Return false if the property was not deleted and is still present. Return true if the property was deleted or is not present.
● The Type of the return value must be Boolean. ● If P was previously observed to be a non-configurable own data or accessor property of the target, [[Delete]] must return false.
[[DefineOwnProperty]]
(propertyKey, PropertyDescriptor) → Boolean
Create or alter the own property, whose key is propertyKey, to have the state described by PropertyDescriptor. Return true if that property was successfully created/updated or false if the property could not be created or updated.
● The Type of the return value must be Boolean. ● [[DefineOwnProperty]] must return false if P has previously been observed as a non-configurable own property of the target, unless either:
- P is a non-configurable writable own data property. A non-configurable writable data property can be changed into a non-configurable non-writable data property.
- All attributes in Desc are the SameValue as P’s attributes. ● [[DefineOwnProperty]] (P, Desc) must return false if target is non-extensible and P is a non-existent own property. That is, a non-extensible target object cannot be extended with new properties.
[[Enumerate]]
()→Object
Return an iterator object that produces the keys of the string-keyed enumerable properties of the object.
● The Type of the return value must be Object.
[[OwnPropertyKeys]]
()→List of propertyKey
Return a List whose elements are all of the own property keys for the object.
● The return value must be a List. ● The Type of each element of the returned List is either String or Symbol. ● The returned List must contain at least the keys of all non-configurable own properties that have previously been observed. ● If the object is non-extensible, the returned List must contain only the keys of all own properties of the object that are observable using [[GetOwnProperty]].
函数对象特有的关键内部方法
[[Call]]
(any, a List of any) → any
Executes code associated with this object. Invoked via a function call expression. The arguments to the internal method are a this value and a list containing the arguments passed to the function by a call expression. Objects that implement this internal method are callable.
[[Construct]]
(a List of any, Object) → Object
Creates an object. Invoked via the new or super operators. The first argument to the internal method is a list containing the arguments of the operator. The second argument is the object to which the new operator was initially applied. Objects that implement this internal method are called constructors. A function object is not necessarily a constructor and such non-constructor function objects do not have a [[Construct]] internal method.
● The Type of the return value must be Object.