页面模式偏好

10 普通对象和异质对象的行为

10.1 普通对象内部方法和内部槽

所有普通对象都有一个名为 [[Prototype]] 的内部槽。此内部槽的值为 null 或对象,并用于实现继承。假设名为 propertyKey 的属性在普通对象 obj 中不存在,但存在于其 [[Prototype]] 对象上。如果 propertyKey 引用 [[Prototype]] 对象上的数据属性,则 obj 会为获取访问继承它,使其表现得就像 propertyKey 是 obj 的属性一样。如果 propertyKey 引用 [[Prototype]] 对象上的可写数据属性,则对 obj 上的 propertyKey 进行设置访问会在 obj 上创建名为 propertyKey 的新数据属性。如果 propertyKey 引用 [[Prototype]] 对象上的不可写数据属性,则对 obj 上的 propertyKey 进行设置访问会失败。如果 propertyKey 引用 [[Prototype]] 对象上的访问器属性,则该访问器会由 obj 为获取访问和设置访问同时继承。

每个普通对象都有一个 Boolean 值的 [[Extensible]] 内部槽,用于满足 6.1.7.3 中规定的与可扩展性相关的内部方法不变量。也就是说,一旦对象的 [[Extensible]] 内部槽值被设置为 false,就不再能够向该对象添加属性、修改对象的 [[Prototype]] 内部槽值,或随后将 [[Extensible]] 的值改回 true。

在以下算法描述中,假定 obj 是普通对象,propertyKey 是属性键值,value 是任意 ECMAScript 语言值,而 propertyDesc 是 Property Descriptor Record。

每个普通对象内部方法都会委托给一个名称相似的抽象操作。如果这样的抽象操作依赖另一个内部方法,则会在 obj 上调用该内部方法,而不是直接调用名称相似的抽象操作。这些语义确保在将普通对象内部方法应用于异质对象时,会调用异质对象所重写的内部方法。

10.1.1 [[GetPrototypeOf]] ( )

an ordinary object obj的内部方法 [[GetPrototypeOf]],接收无参数;返回值:正常完成 (值:(Object 或 null))。 调用时执行以下步骤:

  1. 返回 OrdinaryGetPrototypeOf(obj)。

10.1.1.1 OrdinaryGetPrototypeOf ( obj )

抽象操作 OrdinaryGetPrototypeOf,接收参数 obj (Object);返回值:(Object 或 null)。 调用时执行以下步骤:

  1. 返回 obj.[[Prototype]]。

10.1.2 [[SetPrototypeOf]] ( proto )

an ordinary object obj的内部方法 [[SetPrototypeOf]],接收参数 proto ((Object 或 null));返回值:正常完成 (值:Boolean)。 调用时执行以下步骤:

  1. 返回 OrdinarySetPrototypeOf(obj, proto)。

10.1.2.1 OrdinarySetPrototypeOf ( obj, proto )

抽象操作 OrdinarySetPrototypeOf,接收参数 obj (Object) 和 proto ((Object 或 null));返回值:Boolean。 调用时执行以下步骤:

  1. 令 current 为 obj.[[Prototype]]。
  2. 如果 SameValue(proto, current) 是 true,则返回 true。
  3. 令 extensible 为 obj.[[Extensible]]。
  4. 如果 extensible 是 false,则返回 false。
  5. 令 cursor 为 proto。
  6. 令 done 为 false。
  7. 当 done 是 false 时,重复执行,
    1. 如果 cursor 是 null,则
      1. 将 done 设置为 true。
    2. 否则如果 SameValue(cursor, obj) 是 true,则
      1. 返回 false。
    3. 否则,
      1. 如果 cursor.[[GetPrototypeOf]] 不是 10.1.1 中定义的普通对象内部方法,则将 done 设置为 true。
      2. 否则,将 cursor 设置为 cursor.[[Prototype]]。
  8. 将 obj.[[Prototype]] 设置为 proto。
  9. 返回 true。
注

步骤 7 中的循环保证,在仅包含对 [[GetPrototypeOf]] 和 [[SetPrototypeOf]] 使用普通对象定义的对象的任何原型链中都不会出现循环。

10.1.3 [[IsExtensible]] ( )

an ordinary object obj的内部方法 [[IsExtensible]],接收无参数;返回值:正常完成 (值:Boolean)。 调用时执行以下步骤:

  1. 返回 OrdinaryIsExtensible(obj)。

10.1.3.1 OrdinaryIsExtensible ( obj )

抽象操作 OrdinaryIsExtensible,接收参数 obj (Object);返回值:Boolean。 调用时执行以下步骤:

  1. 返回 obj.[[Extensible]]。

10.1.4 [[PreventExtensions]] ( )

an ordinary object obj的内部方法 [[PreventExtensions]],接收无参数;返回值:正常完成 (值:true)。 调用时执行以下步骤:

  1. 返回 OrdinaryPreventExtensions(obj)。

10.1.4.1 OrdinaryPreventExtensions ( obj )

抽象操作 OrdinaryPreventExtensions,接收参数 obj (Object);返回值:true。 调用时执行以下步骤:

  1. 将 obj.[[Extensible]] 设置为 false。
  2. 返回 true。

10.1.5 [[GetOwnProperty]] ( propertyKey )

an ordinary object obj的内部方法 [[GetOwnProperty]],接收参数 propertyKey (属性键);返回值:正常完成 (值:(属性描述符 或 undefined))。 调用时执行以下步骤:

  1. 返回 OrdinaryGetOwnProperty(obj, propertyKey)。

10.1.5.1 OrdinaryGetOwnProperty ( obj, propertyKey )

抽象操作 OrdinaryGetOwnProperty,接收参数 obj (Object) 和 propertyKey (属性键);返回值:(属性描述符 或 undefined)。 调用时执行以下步骤:

  1. 如果 obj 没有键为 propertyKey 的自有属性,则返回 undefined。
  2. 令 propertyDesc 为一个新创建且没有字段的 Property Descriptor。
  3. 令 ownProperty 为 obj 中键为 propertyKey 的自有属性。
  4. 如果 ownProperty 是数据属性,则
    1. 将 propertyDesc.[[Value]] 设置为 ownProperty 的 [[Value]] 特性的值。
    2. 将 propertyDesc.[[Writable]] 设置为 ownProperty 的 [[Writable]] 特性的值。
  5. 否则,
    1. 断言:ownProperty 是访问器属性。
    2. 将 propertyDesc.[[Getter]] 设置为 ownProperty 的 [[Getter]] 特性的值。
    3. 将 propertyDesc.[[Setter]] 设置为 ownProperty 的 [[Setter]] 特性的值。
  6. 将 propertyDesc.[[Enumerable]] 设置为 ownProperty 的 [[Enumerable]] 特性的值。
  7. 将 propertyDesc.[[Configurable]] 设置为 ownProperty 的 [[Configurable]] 特性的值。
  8. 返回 propertyDesc。

10.1.6 [[DefineOwnProperty]] ( propertyKey, propertyDesc )

an ordinary object obj的内部方法 [[DefineOwnProperty]],接收参数 propertyKey (属性键) 和 propertyDesc (属性描述符);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 返回 ? OrdinaryDefineOwnProperty(obj, propertyKey, propertyDesc)。

10.1.6.1 OrdinaryDefineOwnProperty ( obj, propertyKey, propertyDesc )

抽象操作 OrdinaryDefineOwnProperty,接收参数 obj (Object)、propertyKey (属性键) 和 propertyDesc (属性描述符);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 current 为 ? obj.[[GetOwnProperty]](propertyKey)。
  2. 令 extensible 为 ? IsExtensible(obj)。
  3. 返回 ValidateAndApplyPropertyDescriptor(obj, propertyKey, extensible, propertyDesc, current)。

10.1.6.2 IsCompatiblePropertyDescriptor ( extensible, propertyDesc, current )

抽象操作 IsCompatiblePropertyDescriptor,接收参数 extensible (Boolean)、propertyDesc (属性描述符) 和 current ((属性描述符 或 undefined));返回值:Boolean。 调用时执行以下步骤:

  1. 返回 ValidateAndApplyPropertyDescriptor(undefined, "", extensible, propertyDesc, current)。

10.1.6.3 ValidateAndApplyPropertyDescriptor ( obj, propertyKey, extensible, propertyDesc, current )

抽象操作 ValidateAndApplyPropertyDescriptor,接收参数 obj ((Object 或 undefined))、propertyKey (属性键)、extensible (Boolean)、propertyDesc (属性描述符) 和 current ((属性描述符 或 undefined));返回值:Boolean。 当且仅当 propertyDesc 能够作为具有指定 extensibility 和当前属性 current 的对象的属性应用,同时保持不变量时,它返回 true。当这种应用可行并且 obj 不是 undefined 时,会对名为 propertyKey 的属性执行该应用(必要时会创建该属性)。 调用时执行以下步骤:

  1. 断言:propertyKey 是属性键。
  2. 如果 current 是 undefined,则
    1. 如果 extensible 是 false,则返回 false。
    2. 如果 obj 是 undefined,则返回 true。
    3. 如果 IsAccessorDescriptor(propertyDesc) 是 true,则
      1. 在对象 obj 上创建名为 propertyKey 的自有访问器属性;如果 propertyDesc 具有相应字段,则其 [[Getter]]、[[Setter]]、[[Enumerable]] 和 [[Configurable]] 特性设置为 propertyDesc 中对应字段的值,否则设置为相应特性的默认值。
    4. 否则,
      1. 在对象 obj 上创建名为 propertyKey 的自有数据属性;如果 propertyDesc 具有相应字段,则其 [[Value]]、[[Writable]]、[[Enumerable]] 和 [[Configurable]] 特性设置为 propertyDesc 中对应字段的值,否则设置为相应特性的默认值。
    5. 返回 true。
  3. 断言:current 是完全填充的 Property Descriptor。
  4. 如果 propertyDesc 没有任何字段,则返回 true。
  5. 如果 current.[[Configurable]] 是 false,则
    1. 如果 propertyDesc 具有 [[Configurable]] 字段且 propertyDesc.[[Configurable]] 是 true,则返回 false。
    2. 如果 propertyDesc 具有 [[Enumerable]] 字段且 propertyDesc.[[Enumerable]] 不是 current.[[Enumerable]],则返回 false。
    3. 如果 IsGenericDescriptor(propertyDesc) 是 false 且 IsAccessorDescriptor(propertyDesc) 不等于 IsAccessorDescriptor(current),则返回 false。
    4. 如果 IsAccessorDescriptor(current) 是 true,则
      1. 如果 propertyDesc 具有 [[Getter]] 字段且 SameValue(propertyDesc.[[Getter]], current.[[Getter]]) 是 false,则返回 false。
      2. 如果 propertyDesc 具有 [[Setter]] 字段且 SameValue(propertyDesc.[[Setter]], current.[[Setter]]) 是 false,则返回 false。
    5. 否则如果 current.[[Writable]] 是 false,则
      1. 如果 propertyDesc 具有 [[Writable]] 字段且 propertyDesc.[[Writable]] 是 true,则返回 false。
      2. 注:SameValue 对可能通过其他方式区分的 NaN 值返回 true。在此处返回可确保 obj 的任何现有属性保持不变。
      3. 如果 propertyDesc 具有 [[Value]] 字段,则返回 SameValue(propertyDesc.[[Value]], current.[[Value]])。
  6. 如果 obj 不是 undefined,则
    1. 如果 IsDataDescriptor(current) 是 true 且 IsAccessorDescriptor(propertyDesc) 是 true,则
      1. 如果 propertyDesc 具有 [[Configurable]] 字段,则令 configurable 为 propertyDesc.[[Configurable]];否则令 configurable 为 current.[[Configurable]]。
      2. 如果 propertyDesc 具有 [[Enumerable]] 字段,则令 enumerable 为 propertyDesc.[[Enumerable]];否则令 enumerable 为 current.[[Enumerable]]。
      3. 将对象 obj 中名为 propertyKey 的属性替换为访问器属性,其 [[Configurable]] 和 [[Enumerable]] 特性分别设置为 configurable 和 enumerable;如果 propertyDesc 具有相应字段,则其 [[Getter]] 和 [[Setter]] 特性设置为 propertyDesc 中对应字段的值,否则设置为相应特性的默认值。
    2. 否则如果 IsAccessorDescriptor(current) 是 true 且 IsDataDescriptor(propertyDesc) 是 true,则
      1. 如果 propertyDesc 具有 [[Configurable]] 字段,则令 configurable 为 propertyDesc.[[Configurable]];否则令 configurable 为 current.[[Configurable]]。
      2. 如果 propertyDesc 具有 [[Enumerable]] 字段,则令 enumerable 为 propertyDesc.[[Enumerable]];否则令 enumerable 为 current.[[Enumerable]]。
      3. 将对象 obj 中名为 propertyKey 的属性替换为数据属性,其 [[Configurable]] 和 [[Enumerable]] 特性分别设置为 configurable 和 enumerable;如果 propertyDesc 具有相应字段,则其 [[Value]] 和 [[Writable]] 特性设置为 propertyDesc 中对应字段的值,否则设置为相应特性的默认值。
    3. 否则,
      1. 对 propertyDesc 的每个字段名称 fieldName,将对象 obj 中名为 propertyKey 的属性中名为 fieldName 的特性设置为 propertyDesc 的 fieldName 字段的值。
  7. 返回 true。

10.1.7 [[HasProperty]] ( propertyKey )

an ordinary object obj的内部方法 [[HasProperty]],接收参数 propertyKey (属性键);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 返回 ? OrdinaryHasProperty(obj, propertyKey)。

10.1.7.1 OrdinaryHasProperty ( obj, propertyKey )

抽象操作 OrdinaryHasProperty,接收参数 obj (Object) 和 propertyKey (属性键);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 hasOwn 为 ? obj.[[GetOwnProperty]](propertyKey)。
  2. 如果 hasOwn 不是 undefined,则返回 true。
  3. 令 parent 为 ? obj.[[GetPrototypeOf]]()。
  4. 如果 parent 不是 null,则
    1. 返回 ? parent.[[HasProperty]](propertyKey)。
  5. 返回 false。

10.1.8 [[Get]] ( propertyKey, receiver )

an ordinary object obj的内部方法 [[Get]],接收参数 propertyKey (属性键) 和 receiver (ECMAScript 语言值);返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 返回 ? OrdinaryGet(obj, propertyKey, receiver)。

10.1.8.1 OrdinaryGet ( obj, propertyKey, receiver )

抽象操作 OrdinaryGet,接收参数 obj (Object)、propertyKey (属性键) 和 receiver (ECMAScript 语言值);返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 propertyDesc 为 ? obj.[[GetOwnProperty]](propertyKey)。
  2. 如果 propertyDesc 是 undefined,则
    1. 令 parent 为 ? obj.[[GetPrototypeOf]]()。
    2. 如果 parent 是 null,则返回 undefined。
    3. 返回 ? parent.[[Get]](propertyKey, receiver)。
  3. 如果 IsDataDescriptor(propertyDesc) 是 true,则返回 propertyDesc.[[Value]]。
  4. 断言:IsAccessorDescriptor(propertyDesc) 是 true。
  5. 令 getter 为 propertyDesc.[[Getter]]。
  6. 如果 getter 是 undefined,则返回 undefined。
  7. 返回 ? Call(getter, receiver)。

10.1.9 [[Set]] ( propertyKey, value, receiver )

an ordinary object obj的内部方法 [[Set]],接收参数 propertyKey (属性键)、value (ECMAScript 语言值) 和 receiver (ECMAScript 语言值);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 返回 ? OrdinarySet(obj, propertyKey, value, receiver)。

10.1.9.1 OrdinarySet ( obj, propertyKey, value, receiver )

抽象操作 OrdinarySet,接收参数 obj (Object)、propertyKey (属性键)、value (ECMAScript 语言值) 和 receiver (ECMAScript 语言值);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 ownDesc 为 ? obj.[[GetOwnProperty]](propertyKey)。
  2. 返回 ? OrdinarySetWithOwnDescriptor(obj, propertyKey, value, receiver, ownDesc)。

10.1.9.2 OrdinarySetWithOwnDescriptor ( obj, propertyKey, value, receiver, ownDesc )

抽象操作 OrdinarySetWithOwnDescriptor,接收参数 obj (Object)、propertyKey (属性键)、value (ECMAScript 语言值)、receiver (ECMAScript 语言值) 和 ownDesc ((属性描述符 或 undefined));返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 ownDesc 是 undefined,则
    1. 令 parent 为 ? obj.[[GetPrototypeOf]]()。
    2. 如果 parent 不是 null,则返回 ? parent.[[Set]](propertyKey, value, receiver)。
    3. 将 ownDesc 设置为 PropertyDescriptor { [[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }。
  2. 如果 IsDataDescriptor(ownDesc) 是 true,则
    1. 如果 ownDesc.[[Writable]] 是 false,则返回 false。
    2. 如果 receiver 不是 Object,则返回 false。
    3. 令 existingDesc 为 ? receiver.[[GetOwnProperty]](propertyKey)。
    4. 如果 existingDesc 是 undefined,则
      1. 断言:receiver 当前没有属性 propertyKey。
      2. 返回 ? CreateDataProperty(receiver, propertyKey, value)。
    5. 如果 IsAccessorDescriptor(existingDesc) 是 true,则返回 false。
    6. 如果 existingDesc.[[Writable]] 是 false,则返回 false。
    7. 令 valueDesc 为 PropertyDescriptor { [[Value]]: value }。
    8. 返回 ? receiver.[[DefineOwnProperty]](propertyKey, valueDesc)。
  3. 断言:IsAccessorDescriptor(ownDesc) 是 true。
  4. 令 setter 为 ownDesc.[[Setter]]。
  5. 如果 setter 是 undefined,则返回 false。
  6. 执行 ? Call(setter, receiver, « value »)。
  7. 返回 true。

10.1.10 [[Delete]] ( propertyKey )

an ordinary object obj的内部方法 [[Delete]],接收参数 propertyKey (属性键);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 返回 ? OrdinaryDelete(obj, propertyKey)。

10.1.10.1 OrdinaryDelete ( obj, propertyKey )

抽象操作 OrdinaryDelete,接收参数 obj (Object) 和 propertyKey (属性键);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 propertyDesc 为 ? obj.[[GetOwnProperty]](propertyKey)。
  2. 如果 propertyDesc 是 undefined,则返回 true。
  3. 如果 propertyDesc.[[Configurable]] 是 true,则
    1. 从 obj 中移除名为 propertyKey 的自有属性。
    2. 返回 true。
  4. 返回 false。

10.1.11 [[OwnPropertyKeys]] ( )

an ordinary object obj的内部方法 [[OwnPropertyKeys]],接收无参数;返回值:正常完成 (值:列表 (元素:属性键))。 调用时执行以下步骤:

  1. 返回 OrdinaryOwnPropertyKeys(obj)。

10.1.11.1 OrdinaryOwnPropertyKeys ( obj )

抽象操作 OrdinaryOwnPropertyKeys,接收参数 obj (Object);返回值:列表 (元素:属性键)。 调用时执行以下步骤:

  1. 令 keys 为新的空 List。
  2. 对 obj 的每个自有属性键 propertyKey,其中 propertyKey 是数组索引,按照数值索引升序执行
    1. 将 propertyKey 追加到 keys。
  3. 对 obj 的每个自有属性键 propertyKey,其中 propertyKey 是 String 且 propertyKey 不是数组索引,按照属性创建时间升序执行
    1. 将 propertyKey 追加到 keys。
  4. 对 obj 的每个自有属性键 propertyKey,其中 propertyKey 是 Symbol,按照属性创建时间升序执行
    1. 将 propertyKey 追加到 keys。
  5. 返回 keys。

10.1.12 OrdinaryObjectCreate ( proto [ , additionalInternalSlotsList ] )

抽象操作 OrdinaryObjectCreate,接收参数 proto ((Object 或 null))和可选参数 additionalInternalSlotsList (列表 (元素:内部槽名称));返回值:Object。 它用于规定新普通对象的运行时创建。additionalInternalSlotsList 包含除 [[Prototype]] 和 [[Extensible]] 之外,必须作为对象一部分定义的附加内部槽名称。如果未提供 additionalInternalSlotsList,则使用新的空 List。 调用时执行以下步骤:

  1. 令 internalSlotsList 为 « [[Prototype]], [[Extensible]] »。
  2. 如果存在 additionalInternalSlotsList,则将 internalSlotsList 设置为 internalSlotsList 和 additionalInternalSlotsList 的列表连接。
  3. 令 obj 为 MakeBasicObject(internalSlotsList)。
  4. 将 obj.[[Prototype]] 设置为 proto。
  5. 返回 obj。
注

尽管 OrdinaryObjectCreate 所做的事情几乎只是调用 MakeBasicObject,但使用它表达了创建普通对象而非异质对象的意图。因此,在本规范中,任何随后会以使结果变为非普通对象的方式修改对象内部方法的算法都不会调用它。创建异质对象的操作会直接调用 MakeBasicObject。

10.1.13 OrdinaryCreateFromConstructor ( ctor, intrinsicDefaultProto [ , internalSlotsList ] )

抽象操作 OrdinaryCreateFromConstructor,接收参数 ctor (函数对象) 和 intrinsicDefaultProto (String)和可选参数 internalSlotsList (列表 (元素:内部槽名称));返回值:(正常完成 (值:Object) 或 抛出完成)。 它创建一个普通对象;如果构造函数存在 "prototype" 属性,则从该属性取得其 [[Prototype]] 值。否则,使用由 intrinsicDefaultProto 命名的内在对象作为 [[Prototype]]。internalSlotsList 包含必须作为对象一部分定义的附加内部槽名称。如果未提供 internalSlotsList,则使用新的空 List。 调用时执行以下步骤:

  1. 断言:intrinsicDefaultProto 是本规范中某个内在对象的名称。对应对象必须是预期用作对象 [[Prototype]] 值的内在对象。
  2. 令 proto 为 ? GetPrototypeFromConstructor(ctor, intrinsicDefaultProto)。
  3. 如果存在 internalSlotsList,则令 slots 为 internalSlotsList。
  4. 否则,令 slots 为新的空 List。
  5. 返回 OrdinaryObjectCreate(proto, slots)。

10.1.14 GetPrototypeFromConstructor ( ctor, intrinsicDefaultProto )

抽象操作 GetPrototypeFromConstructor,接收参数 ctor (函数对象) 和 intrinsicDefaultProto (String);返回值:(正常完成 (值:Object) 或 抛出完成)。 它确定创建与特定构造函数对应的对象时应使用的 [[Prototype]] 值。如果构造函数存在 "prototype" 属性,则从该属性获取该值。否则,使用由 intrinsicDefaultProto 命名的内在对象作为 [[Prototype]]。 调用时执行以下步骤:

  1. 断言:intrinsicDefaultProto 是本规范中某个内在对象的名称。对应对象必须是预期用作对象 [[Prototype]] 值的内在对象。
  2. 令 proto 为 ? Get(ctor, "prototype")。
  3. 如果 proto 不是 Object,则
    1. 令 realm 为 ? GetFunctionRealm(ctor)。
    2. 将 proto 设置为 realm 中名为 intrinsicDefaultProto 的内在对象。
  4. 返回 proto。
注

如果 ctor 不提供 [[Prototype]] 值,则使用的默认值取自 ctor 函数的 Realm,而不是正在运行的执行上下文。

10.1.15 RequireInternalSlot ( obj, internalSlot )

抽象操作 RequireInternalSlot,接收参数 obj (ECMAScript 语言值) 和 internalSlot (内部槽名称);返回值:(正常完成 (值:unused) 或 抛出完成)。 除非 obj 是 Object 且具有给定内部槽,否则它会抛出异常。 调用时执行以下步骤:

  1. 如果 obj 不是 Object,则抛出 TypeError 异常。
  2. 如果 obj 没有 internalSlot 内部槽,则抛出 TypeError 异常。
  3. 返回 unused。

10.2 ECMAScript 函数对象

ECMAScript 函数对象封装了闭包于某个词法环境之上的参数化 ECMAScript 代码,并支持对该代码进行动态求值。ECMAScript 函数对象是普通对象,并具有与其他普通对象相同的内部槽和内部方法。ECMAScript 函数对象的代码可以是严格模式代码(11.2.2),也可以是非严格模式代码。其代码为严格模式代码的 ECMAScript 函数对象称为严格函数。其代码不是严格模式代码的 ECMAScript 函数对象称为非严格函数。

除 [[Extensible]] 和 [[Prototype]] 外,ECMAScript 函数对象还具有 表 26 中列出的内部槽。

表 26: ECMAScript 函数对象的内部槽
内部槽 类型 描述
[[Environment]] Environment Record 函数闭包所捕获的 Environment Record。在对函数代码求值时用作外层环境。
[[PrivateEnvironment]] PrivateEnvironment Record 或 null 函数闭包所捕获的 Private Name 对应的 PrivateEnvironment Record。如果此函数在句法上不包含在类中,则为 null。在对函数代码求值时,用作内部类的外层 PrivateEnvironment。
[[FormalParameters]] Parse Node 定义函数形式参数列表的源文本的根解析节点。
[[ECMAScriptCode]] Parse Node 定义函数主体的源文本的根解析节点。
[[ConstructorKind]] base 或 derived 函数是否为派生类构造函数。
[[Realm]] Realm Record 创建该函数的 Realm,并提供对函数求值时所访问的任何内在对象。
[[ScriptOrModule]] Script Record 或 Module Record 创建该函数的脚本或模块。
[[ThisMode]] lexical、strict 或 global 定义如何解释函数形式参数和代码主体中的 this 引用。lexical 表示 this 引用词法包围函数的 this 值。strict 表示 this 值完全按函数调用时提供的值使用。global 表示 undefined 或 null 的 this 值被解释为对全局对象的引用,而任何其他 this 值都会先传给 ToObject。
[[Strict]] Boolean 如果这是严格函数,则为 true;如果这是非严格函数,则为 false。
[[HomeObject]] Object 或 undefined 如果函数使用 super,则这是其 [[GetPrototypeOf]] 提供 super 属性查找起始对象的对象。
[[SourceText]] Unicode 码点序列 定义函数的源文本。
[[Fields]] ClassFieldDefinition Record 的 List 如果函数是类,则这是表示类的非静态字段及其对应初始化器的 Record 列表。
[[PrivateMethods]] PrivateElement 的 List 如果函数是类,则这是表示类的非静态私有方法和访问器的列表。
[[ClassFieldInitializerName]] String、Symbol、Private Name 或 empty 如果函数是作为类字段的初始化器创建的,则这是用于该字段 NamedEvaluation 的名称;否则为 empty。
[[IsClassConstructor]] Boolean 指示函数是否为类构造函数。(如果为 true,调用函数的 [[Call]] 会立即抛出 TypeError 异常。)

所有 ECMAScript 函数对象都具有此处定义的 [[Call]] 内部方法。除此之外,同时也是构造函数的 ECMAScript 函数还具有 [[Construct]] 内部方法。

10.2.1 [[Call]] ( thisArg, argList )

an ECMAScript function object func的内部方法 [[Call]],接收参数 thisArg (ECMAScript 语言值) 和 argList (列表 (元素:ECMAScript 语言值));返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 callerContext 为正在运行的执行上下文。
  2. 令 calleeContext 为 PrepareForOrdinaryCall(func, undefined)。
  3. 断言:calleeContext 现在是正在运行的执行上下文。
  4. 如果 func.[[IsClassConstructor]] 是 true,则
    1. 令 error 为新创建的 TypeError 对象。
    2. 注:error 在 calleeContext 中使用与 func 关联的 Realm Record 创建。
    3. 从执行上下文栈中移除 calleeContext,并恢复 callerContext 作为正在运行的执行上下文。
    4. 抛出 error。
  5. 执行 OrdinaryCallBindThis(func, calleeContext, thisArg)。
  6. 令 result 为 Completion(OrdinaryCallEvaluateBody(func, argList))。
  7. 从执行上下文栈中移除 calleeContext,并恢复 callerContext 作为正在运行的执行上下文。
  8. 如果 result 是抛出完成,则返回 ? result。
  9. 断言:result 是 return 完成。
  10. 返回 result.[[Value]]。
注

当步骤 7 中从执行上下文栈移除 calleeContext 时,如果它已暂停并由可访问的 Generator 保留以供以后恢复,则不得销毁它。

10.2.1.1 PrepareForOrdinaryCall ( func, newTarget )

抽象操作 PrepareForOrdinaryCall,接收参数 func (ECMAScript 函数对象) 和 newTarget ((Object 或 undefined));返回值:执行上下文。 调用时执行以下步骤:

  1. 令 callerContext 为正在运行的执行上下文。
  2. 令 calleeContext 为新的 ECMAScript 代码执行上下文。
  3. 将 calleeContext 的 Function 设置为 func。
  4. 令 calleeRealm 为 func.[[Realm]]。
  5. 将 calleeContext 的 Realm 设置为 calleeRealm。
  6. 将 calleeContext 的 ScriptOrModule 设置为 func.[[ScriptOrModule]]。
  7. 令 localEnv 为 NewFunctionEnvironment(func, newTarget)。
  8. 将 calleeContext 的 LexicalEnvironment 设置为 localEnv。
  9. 将 calleeContext 的 VariableEnvironment 设置为 localEnv。
  10. 将 calleeContext 的 PrivateEnvironment 设置为 func.[[PrivateEnvironment]]。
  11. 如果 callerContext 尚未暂停,则暂停 callerContext。
  12. 将 calleeContext 压入执行上下文栈;calleeContext 现在是正在运行的执行上下文。
  13. 注:从此处之后产生的任何异常对象都与 calleeRealm 关联。
  14. 返回 calleeContext。

10.2.1.2 OrdinaryCallBindThis ( func, calleeContext, thisArg )

抽象操作 OrdinaryCallBindThis,接收参数 func (ECMAScript 函数对象)、calleeContext (执行上下文) 和 thisArg (ECMAScript 语言值);返回值:unused。 调用时执行以下步骤:

  1. 令 thisMode 为 func.[[ThisMode]]。
  2. 如果 thisMode 是 lexical,则返回 unused。
  3. 令 calleeRealm 为 func.[[Realm]]。
  4. 令 localEnv 为 calleeContext 的 LexicalEnvironment。
  5. 如果 thisMode 是 strict,则
    1. 令 thisValue 为 thisArg。
  6. 否则,
    1. 如果 thisArg 是 undefined 或 null,则
      1. 令 globalEnv 为 calleeRealm.[[GlobalEnv]]。
      2. 断言:globalEnv 是 Global Environment Record。
      3. 令 thisValue 为 globalEnv.[[GlobalThisValue]]。
    2. 否则,
      1. 令 thisValue 为 ! ToObject(thisArg)。
      2. 注:ToObject 使用 calleeRealm 创建包装对象。
  7. 断言:localEnv 是 Function Environment Record。
  8. 断言:由于 localEnv.[[ThisBindingStatus]] 不是 initialized,所以下一步永远不会返回突然完成。
  9. 执行 ! BindThisValue(localEnv, thisValue)。
  10. 返回 unused。

10.2.1.3 Runtime Semantics: EvaluateBody

语法制导操作 EvaluateBody,接收参数 func (ECMAScript 函数对象) 和 argList (列表 (元素:ECMAScript 语言值));返回值:(返回完成 或 抛出完成)。 它按以下产生式分别定义:

FunctionBody : FunctionStatementList
  1. 返回 ? 以 func 和 argList 为参数对 FunctionBody 执行 EvaluateFunctionBody 的结果。
ConciseBody : ExpressionBody
  1. 返回 ? 以 func 和 argList 为参数对 ConciseBody 执行 EvaluateConciseBody 的结果。
GeneratorBody : FunctionBody
  1. 返回 ? 以 func 和 argList 为参数对 GeneratorBody 执行 EvaluateGeneratorBody 的结果。
AsyncGeneratorBody : FunctionBody
  1. 返回 ? 以 func 和 argList 为参数对 AsyncGeneratorBody 执行 EvaluateAsyncGeneratorBody 的结果。
AsyncFunctionBody : FunctionBody
  1. 返回 ? 以 func 和 argList 为参数对 AsyncFunctionBody 执行 EvaluateAsyncFunctionBody 的结果。
AsyncConciseBody : ExpressionBody
  1. 返回 ? 以 func 和 argList 为参数对 AsyncConciseBody 执行 EvaluateAsyncConciseBody 的结果。
Initializer : = AssignmentExpression
  1. 断言:argList 为空。
  2. 断言:func.[[ClassFieldInitializerName]] 不是 empty。
  3. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 是 true,则
    1. 令 value 为 ? 以 func.[[ClassFieldInitializerName]] 为参数对 Initializer 执行 NamedEvaluation 的结果。
  4. 否则,
    1. 令 rhs 为 ? AssignmentExpression 的 Evaluation。
    2. 令 value 为 ? GetValue(rhs)。
  5. 返回 ReturnCompletion(value)。
注

即使字段初始化器构成函数边界,调用 FunctionDeclarationInstantiation 也没有任何可观察效果,因此被省略。

ClassStaticBlockBody : ClassStaticBlockStatementList
  1. 断言:argList 为空。
  2. 返回 ? 以 func 为参数对 ClassStaticBlockBody 执行 EvaluateClassStaticBlockBody 的结果。

10.2.1.4 OrdinaryCallEvaluateBody ( func, argList )

抽象操作 OrdinaryCallEvaluateBody,接收参数 func (ECMAScript 函数对象) 和 argList (列表 (元素:ECMAScript 语言值));返回值:(返回完成 或 抛出完成)。 调用时执行以下步骤:

  1. 返回 ? 以 func 和 argList 为参数对 func.[[ECMAScriptCode]] 执行 EvaluateBody 的结果。

10.2.2 [[Construct]] ( argList, newTarget )

an ECMAScript function object func的内部方法 [[Construct]],接收参数 argList (列表 (元素:ECMAScript 语言值)) 和 newTarget (构造函数);返回值:(正常完成 (值:Object) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 callerContext 为正在运行的执行上下文。
  2. 令 kind 为 func.[[ConstructorKind]]。
  3. 如果 kind 是 base,则
    1. 令 thisArg 为 ? OrdinaryCreateFromConstructor(newTarget, "%Object.prototype%")。
  4. 令 calleeContext 为 PrepareForOrdinaryCall(func, newTarget)。
  5. 断言:calleeContext 现在是正在运行的执行上下文。
  6. 如果 kind 是 base,则
    1. 执行 OrdinaryCallBindThis(func, calleeContext, thisArg)。
    2. 令 initializeResult 为 Completion(InitializeInstanceElements(thisArg, func))。
    3. 如果 initializeResult 是突然完成,则
      1. 从执行上下文栈中移除 calleeContext,并恢复 callerContext 作为正在运行的执行上下文。
      2. 返回 ? initializeResult。
  7. 令 ctorEnv 为 calleeContext 的 LexicalEnvironment。
  8. 令 result 为 Completion(OrdinaryCallEvaluateBody(func, argList))。
  9. 从执行上下文栈中移除 calleeContext,并恢复 callerContext 作为正在运行的执行上下文。
  10. 如果 result 是抛出完成,则返回 ? result。
  11. 断言:result 是 return 完成。
  12. 如果 result.[[Value]] 是 Object,则返回 result.[[Value]]。
  13. 如果 kind 是 base,则返回 thisArg。
  14. 如果 result.[[Value]] 不是 undefined,则抛出 TypeError 异常。
  15. 令 thisBinding 为 ? ctorEnv.GetThisBinding()。
  16. 断言:thisBinding 是 Object。
  17. 返回 thisBinding。

10.2.3 OrdinaryFunctionCreate ( proto, sourceText, paramList, body, thisMode, envRecord, privateEnv )

抽象操作 OrdinaryFunctionCreate,接收参数 proto (Object)、sourceText (a sequence of Unicode code points)、paramList (解析节点)、body (解析节点)、thisMode ((lexical-this 或 non-lexical-this))、envRecord (Environment 记录) 和 privateEnv ((PrivateEnvironment 记录 或 null));返回值:ECMAScript 函数对象。 它用于规定运行时创建一个新的函数,该函数具有默认的 [[Call]] 内部方法且没有 [[Construct]] 内部方法(尽管随后可能通过 MakeConstructor 等操作添加)。sourceText 是要创建函数的句法定义的源文本。 调用时执行以下步骤:

  1. 令 internalSlotsList 为 表 26 中列出的内部槽。
  2. 令 func 为 OrdinaryObjectCreate(proto, internalSlotsList)。
  3. 将 func.[[Call]] 设置为 10.2.1 中规定的定义。
  4. 将 func.[[SourceText]] 设置为 sourceText。
  5. 将 func.[[FormalParameters]] 设置为 paramList。
  6. 将 func.[[ECMAScriptCode]] 设置为 body。
  7. 令 strict 为 IsStrict(body)。
  8. 将 func.[[Strict]] 设置为 strict。
  9. 如果 thisMode 是 lexical-this,则将 func.[[ThisMode]] 设置为 lexical。
  10. 否则如果 strict 是 true,则将 func.[[ThisMode]] 设置为 strict。
  11. 否则,将 func.[[ThisMode]] 设置为 global。
  12. 将 func.[[IsClassConstructor]] 设置为 false。
  13. 将 func.[[Environment]] 设置为 envRecord。
  14. 将 func.[[PrivateEnvironment]] 设置为 privateEnv。
  15. 将 func.[[ScriptOrModule]] 设置为 GetActiveScriptOrModule()。
  16. 将 func.[[Realm]] 设置为当前 Realm Record。
  17. 将 func.[[HomeObject]] 设置为 undefined。
  18. 将 func.[[Fields]] 设置为新的空 List。
  19. 将 func.[[PrivateMethods]] 设置为新的空 List。
  20. 将 func.[[ClassFieldInitializerName]] 设置为 empty。
  21. 令 length 为 paramList 的 ExpectedArgumentCount。
  22. 执行 SetFunctionLength(func, length)。
  23. 返回 func。

10.2.4 AddRestrictedFunctionProperties ( func, realm )

抽象操作 AddRestrictedFunctionProperties,接收参数 func (函数对象) 和 realm (Realm 记录);返回值:unused。 调用时执行以下步骤:

  1. 断言:realm.[[Intrinsics]].[[%ThrowTypeError%]] 存在且已初始化。
  2. 令 thrower 为 realm.[[Intrinsics]].[[%ThrowTypeError%]]。
  3. 执行 ! DefinePropertyOrThrow(func, "caller", PropertyDescriptor { [[Getter]]: thrower, [[Setter]]: thrower, [[Enumerable]]: false, [[Configurable]]: true })。
  4. 执行 ! DefinePropertyOrThrow(func, "arguments", PropertyDescriptor { [[Getter]]: thrower, [[Setter]]: thrower, [[Enumerable]]: false, [[Configurable]]: true })。
  5. 返回 unused。

10.2.4.1 %ThrowTypeError% ( )

此函数是 %ThrowTypeError% 内在对象。

它是一个匿名内置函数对象,每个 Realm 定义一次。

调用时,它执行以下步骤:

  1. 抛出 TypeError 异常。

此函数的 [[Extensible]] 内部槽值为 false。

此函数的 "length" 属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

此函数的 "name" 属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

10.2.5 MakeConstructor ( func [ , writableProto [ , proto ] ] )

抽象操作 MakeConstructor,接收参数 func ((ECMAScript 函数对象 或 内置函数对象))和可选参数 writableProto (Boolean) 和 proto (Object);返回值:unused。 它将 func 转换为构造函数。 调用时执行以下步骤:

  1. 如果 func 是 ECMAScript 函数对象,则
    1. 断言:IsConstructor(func) 是 false。
    2. 断言:func 是可扩展对象,并且没有 "prototype" 自有属性。
    3. 将 func.[[Construct]] 设置为 10.2.2 中规定的定义。
  2. 否则,
    1. 将 func.[[Construct]] 设置为 10.3.2 中规定的定义。
  3. 将 func.[[ConstructorKind]] 设置为 base。
  4. 如果不存在 writableProto,则将 writableProto 设置为 true。
  5. 如果不存在 proto,则
    1. 将 proto 设置为 OrdinaryObjectCreate(%Object.prototype%)。
    2. 执行 ! DefinePropertyOrThrow(proto, "constructor", PropertyDescriptor { [[Value]]: func, [[Writable]]: writableProto, [[Enumerable]]: false, [[Configurable]]: true })。
  6. 执行 ! DefinePropertyOrThrow(func, "prototype", PropertyDescriptor { [[Value]]: proto, [[Writable]]: writableProto, [[Enumerable]]: false, [[Configurable]]: false })。
  7. 返回 unused。

10.2.6 MakeClassConstructor ( func )

抽象操作 MakeClassConstructor,接收参数 func (ECMAScript 函数对象);返回值:unused。 调用时执行以下步骤:

  1. 断言:func.[[IsClassConstructor]] 是 false。
  2. 将 func.[[IsClassConstructor]] 设置为 true。
  3. 返回 unused。

10.2.7 MakeMethod ( func, homeObj )

抽象操作 MakeMethod,接收参数 func (ECMAScript 函数对象) 和 homeObj (Object);返回值:unused。 它将 func 配置为方法。 调用时执行以下步骤:

  1. 断言:homeObj 是普通对象。
  2. 将 func.[[HomeObject]] 设置为 homeObj。
  3. 返回 unused。

10.2.8 DefineMethodProperty ( homeObj, name, closure, enumerable )

抽象操作 DefineMethodProperty,接收参数 homeObj (Object)、name ((属性键 或 私有名称))、closure (函数对象) 和 enumerable (Boolean);返回值:(正常完成 (值:(PrivateElement 或 empty)) 或 突兀完成)。 调用时执行以下步骤:

  1. 断言:homeObj 是普通、可扩展对象。
  2. 如果 name 是 Private Name,则返回 PrivateElement { [[Key]]: name, [[Kind]]: method, [[Value]]: closure }。
  3. 令 propertyDesc 为 PropertyDescriptor { [[Value]]: closure, [[Writable]]: true, [[Enumerable]]: enumerable, [[Configurable]]: true }。
  4. 执行 ? DefinePropertyOrThrow(homeObj, name, propertyDesc)。
  5. 注:DefinePropertyOrThrow 仅在尝试定义 name 为 "prototype" 的类静态方法时返回突然完成。
  6. 返回 empty。

10.2.9 SetFunctionName ( func, name [ , prefix ] )

抽象操作 SetFunctionName,接收参数 func (函数对象) 和 name ((属性键 或 私有名称))和可选参数 prefix (String);返回值:unused。 它向 func 添加 "name" 属性。 调用时执行以下步骤:

  1. 断言:func 是可扩展对象,且没有 "name" 自有属性。
  2. 如果 name 是 Symbol,则
    1. 令 description 为 name.[[Description]]。
    2. 如果 description 是 undefined,则将 name 设置为空 String。
    3. 否则,将 name 设置为 "["、description 和 "]" 的字符串连接。
  3. 否则如果 name 是 Private Name,则
    1. 将 name 设置为 name.[[Description]]。
  4. 令 initialName 为 name。
  5. 如果存在 prefix,则
    1. 令 prefixedName 为 prefix、码元 0x0020 (SPACE) 和 name 的字符串连接。
    2. 将 initialName 设置为 prefixedName。
    3. Normative Optional, Legacy
      将 initialName 设置为实现定义地从 name 或 prefixedName 中选择的一个值。
    4. 将 name 设置为 prefixedName。
  6. 如果 func 具有 [[InitialName]] 内部槽,则将 func.[[InitialName]] 设置为 initialName。
  7. 执行 ! DefinePropertyOrThrow(func, "name", PropertyDescriptor { [[Value]]: name, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true })。
  8. 返回 unused。
注

是否为 func.[[InitialName]] 使用 prefixedName 的选择会影响 Function.prototype.toString ( ) 的输出。在步骤 5.c 中针对不同内置函数做出不同选择,是不鼓励使用的遗留行为。

10.2.10 SetFunctionLength ( func, length )

抽象操作 SetFunctionLength,接收参数 func (函数对象) 和 length ((非负整数 或 +∞));返回值:unused。 它向 func 添加 "length" 属性。 调用时执行以下步骤:

  1. 断言:func 是可扩展对象,且没有 "length" 自有属性。
  2. 执行 ! DefinePropertyOrThrow(func, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true })。
  3. 返回 unused。

10.2.11 FunctionDeclarationInstantiation ( func, argList )

抽象操作 FunctionDeclarationInstantiation,接收参数 func (ECMAScript 函数对象) 和 argList (列表 (元素:ECMAScript 语言值));返回值:(正常完成 (值:unused) 或 抛出完成)。 func 是正在为其建立执行上下文的函数对象。

注

为对 ECMAScript 函数求值而建立执行上下文时,会创建一个新的 Function Environment Record,并在该 Environment Record 中实例化每个形式参数的绑定。函数主体中的每个声明也会被实例化。如果函数的形式参数不包含任何默认值初始化器,则主体声明会在与参数相同的 Environment Record 中实例化。如果存在默认值参数初始化器,则会为主体声明创建第二个 Environment Record。形式参数和函数会作为 FunctionDeclarationInstantiation 的一部分进行初始化。所有其他绑定都会在函数主体求值期间初始化。

调用时,它执行以下步骤:

  1. 令 calleeContext 为正在运行的执行上下文。
  2. 令 code 为 func.[[ECMAScriptCode]]。
  3. 令 strict 为 func.[[Strict]]。
  4. 令 formals 为 func.[[FormalParameters]]。
  5. 令 paramNames 为 formals 的 BoundNames。
  6. 如果 paramNames 有任何重复条目,则令 hasDuplicates 为 true;否则令 hasDuplicates 为 false。
  7. 令 simpleParamList 为 formals 的 IsSimpleParameterList。
  8. 令 hasParamExprs 为 formals 的 ContainsExpression。
  9. 令 variableNames 为 code 的 VarDeclaredNames。
  10. 令 variableDecls 为 code 的 VarScopedDeclarations。
  11. 令 lexicalNames 为 code 的 LexicallyDeclaredNames。
  12. 令 funcNames 为新的空 List。
  13. 令 funcsToInitialize 为新的空 List。
  14. 对 variableDecls 的每个元素 variableDecl,按照 List 的逆序执行
    1. 如果 variableDecl 既不是 VariableDeclaration、也不是 ForBinding、也不是 BindingIdentifier,则
      1. 断言:variableDecl 是 FunctionDeclaration、GeneratorDeclaration、AsyncFunctionDeclaration 或 AsyncGeneratorDeclaration 之一。
      2. 令 funcName 为 variableDecl 的 BoundNames 的唯一元素。
      3. 如果 funcNames 不包含 funcName,则
        1. 将 funcName 插入为 funcNames 的第一个元素。
        2. 注:如果同一个名称有多个函数声明,则使用最后一个声明。
        3. 将 variableDecl 插入为 funcsToInitialize 的第一个元素。
  15. 令 argumentsObjNeeded 为 true。
  16. 如果 func.[[ThisMode]] 是 lexical,则
    1. 注:箭头函数永远没有 arguments 对象。
    2. 将 argumentsObjNeeded 设置为 false。
  17. 否则如果 paramNames 包含 "arguments",则
    1. 将 argumentsObjNeeded 设置为 false。
  18. 否则如果 hasParamExprs 是 false,则
    1. 如果 funcNames 包含 "arguments" 或 lexicalNames 包含 "arguments",则
      1. 将 argumentsObjNeeded 设置为 false。
  19. 如果 strict 是 true 或 hasParamExprs 是 false,则
    1. 注:参数只需要单个 Environment Record,因为严格模式代码中的 eval 调用无法创建在 eval 外部可见的新绑定。
    2. 令 envRecord 为 calleeContext 的 LexicalEnvironment。
  20. 否则,
    1. 注:需要单独的 Environment Record,以确保形式参数列表中的直接 eval 调用创建的绑定位于声明参数的环境之外。
    2. 令 calleeEnv 为 calleeContext 的 LexicalEnvironment。
    3. 令 envRecord 为 NewDeclarativeEnvironment(calleeEnv)。
    4. 断言:calleeContext 的 VariableEnvironment 与 calleeEnv 是同一个 Environment Record。
    5. 将 calleeContext 的 LexicalEnvironment 设置为 envRecord。
  21. 对 paramNames 的每个 String paramName,执行
    1. 令 alreadyDeclared 为 ! envRecord.HasBinding(paramName)。
    2. 注:提前错误确保,只有在没有参数默认值或剩余参数的非严格函数中才可能出现重复参数名称。
    3. 如果 alreadyDeclared 是 false,则
      1. 执行 ! envRecord.CreateMutableBinding(paramName, false)。
      2. 如果 hasDuplicates 是 true,则
        1. 执行 ! envRecord.InitializeBinding(paramName, undefined)。
  22. 如果 argumentsObjNeeded 是 true,则
    1. 如果 strict 是 true 或 simpleParamList 是 false,则
      1. 令 argumentsObj 为 CreateUnmappedArgumentsObject(argList)。
    2. 否则,
      1. 注:映射 arguments 对象仅为没有剩余参数、没有任何参数默认值初始化器、也没有任何解构参数的非严格函数提供。
      2. 令 argumentsObj 为 CreateMappedArgumentsObject(func, formals, argList, envRecord)。
    3. 如果 strict 是 true,则
      1. 执行 ! envRecord.CreateImmutableBinding("arguments", false)。
      2. 注:在严格模式代码中,提前错误会阻止尝试对此绑定进行赋值,因此其可变性不可观察。
    4. 否则,
      1. 执行 ! envRecord.CreateMutableBinding("arguments", false)。
    5. 执行 ! envRecord.InitializeBinding("arguments", argumentsObj)。
    6. 令 paramBindings 为 paramNames 与 « "arguments" » 的列表连接。
  23. 否则,
    1. 令 paramBindings 为 paramNames。
  24. 令 iteratorRecord 为 CreateListIteratorRecord(argList)。
  25. 如果 hasDuplicates 是 true,则
    1. 令 usedEnv 为 undefined。
  26. 否则,
    1. 令 usedEnv 为 envRecord。
  27. 注:以下步骤无法返回 ReturnCompletion,因为在表达式位置产生这种完成的唯一方式是使用 YieldExpression,而 15.5.1 和 15.6.1 中的提前错误规则禁止在参数列表中使用它。
  28. 执行 ? 以 iteratorRecord 和 usedEnv 为参数对 formals 执行 IteratorBindingInitialization。
  29. 如果 hasParamExprs 是 false,则
    1. 注:参数和顶层 var 只需要单个 Environment Record。
    2. 令 instantiatedVariableNames 为 List paramBindings 的副本。
    3. 对 variableNames 的每个元素 name,执行
      1. 如果 instantiatedVariableNames 不包含 name,则
        1. 将 name 追加到 instantiatedVariableNames。
        2. 执行 ! envRecord.CreateMutableBinding(name, false)。
        3. 执行 ! envRecord.InitializeBinding(name, undefined)。
    4. 令 variableEnv 为 envRecord。
  30. 否则,
    1. 注:需要单独的 Environment Record,以确保由形式参数列表中的表达式创建的闭包看不到函数主体中的声明。
    2. 令 variableEnv 为 NewDeclarativeEnvironment(envRecord)。
    3. 将 calleeContext 的 VariableEnvironment 设置为 variableEnv。
    4. 令 instantiatedVariableNames 为新的空 List。
    5. 对 variableNames 的每个元素 name,执行
      1. 如果 instantiatedVariableNames 不包含 name,则
        1. 将 name 追加到 instantiatedVariableNames。
        2. 执行 ! variableEnv.CreateMutableBinding(name, false)。
        3. 如果 paramBindings 不包含 name 或 funcNames 包含 name,则
          1. 令 initialValue 为 undefined。
        4. 否则,
          1. 令 initialValue 为 ! envRecord.GetBindingValue(name, false)。
        5. 执行 ! variableEnv.InitializeBinding(name, initialValue)。
        6. 注:与形式参数同名的 var 最初具有与对应已初始化参数相同的值。
  31. 如果 strict 是 true,则
    1. 令 lexicalEnv 为 variableEnv。
  32. 否则,
    1. Normative Optional
      如果宿主是 Web 浏览器或以其他方式支持 块级函数声明的 Web 遗留兼容性语义,则
      1. 对任何 Block、CaseClause 或 DefaultClause x 的 StatementList 中直接包含的每个 FunctionDeclaration funcDecl,且 code Contains x 是 true,执行
        1. 令 funcName 为 funcDecl 的 BindingIdentifier 的 StringValue。
        2. 如果将 FunctionDeclaration funcDecl 替换为一个以 funcName 作为 BindingIdentifier 的 VariableStatement 不会为 func 产生任何提前错误,并且 paramNames 不包含 funcName,则
          1. 注:只有当 funcName 既不是 VarDeclaredName、也不是形式参数名称、也不是另一个 FunctionDeclaration 的名称时,才会在此处为 funcName 实例化 var 绑定。
          2. 如果 instantiatedVariableNames 不包含 funcName 且 funcName 不是 "arguments",则
            1. 执行 ! variableEnv.CreateMutableBinding(funcName, false)。
            2. 执行 ! variableEnv.InitializeBinding(funcName, undefined)。
            3. 将 funcName 追加到 instantiatedVariableNames。
          3. 当对 FunctionDeclaration funcDecl 求值时,执行以下步骤,以代替 15.2.6 中提供的 FunctionDeclaration Evaluation 算法:
            1. 令 funcEnv 为正在运行的执行上下文的 VariableEnvironment。
            2. 令 blockEnv 为正在运行的执行上下文的 LexicalEnvironment。
            3. 令 funcObj 为 ! blockEnv.GetBindingValue(funcName, false)。
            4. 执行 ! funcEnv.SetMutableBinding(funcName, funcObj, false)。
            5. 返回 unused。
    2. 令 lexicalEnv 为 NewDeclarativeEnvironment(variableEnv)。
    3. 注:非严格函数为顶层词法声明使用单独的 Environment Record,以便直接 eval 能够确定 eval 代码引入的任何 var 作用域声明是否与预先存在的顶层词法作用域声明冲突。严格函数不需要这样做,因为严格模式直接 eval 始终将所有声明放入新的 Environment Record。
  33. 将 calleeContext 的 LexicalEnvironment 设置为 lexicalEnv。
  34. 令 lexicalDecls 为 code 的 LexicallyScopedDeclarations。
  35. 对 lexicalDecls 的每个元素 lexicalDecl,执行
    1. 注:词法声明名称不能与函数/生成器声明、形式参数或 var 名称相同。词法声明名称仅在此处实例化,但不初始化。
    2. 对 lexicalDecl 的 BoundNames 的每个元素 name,执行
      1. 如果 lexicalDecl 的 IsConstantDeclaration 是 true,则
        1. 执行 ! lexicalEnv.CreateImmutableBinding(name, true)。
      2. 否则,
        1. 执行 ! lexicalEnv.CreateMutableBinding(name, false)。
  36. 令 privateEnv 为 calleeContext 的 PrivateEnvironment。
  37. 对 funcsToInitialize 的每个 Parse Node funcDecl,执行
    1. 令 funcName 为 funcDecl 的 BoundNames 的唯一元素。
    2. 令 funcObj 为以 lexicalEnv 和 privateEnv 为参数对 funcDecl 执行 InstantiateFunctionObject 的结果。
    3. 执行 ! variableEnv.SetMutableBinding(funcName, funcObj, false)。
  38. 返回 unused。

10.3 内置函数对象

内置函数对象是普通对象;它必须满足 10.1 中规定的普通对象要求。

除每个普通对象所需的内部槽(参见 10.1)之外,内置函数对象还必须具有以下内部槽:

  • [[Realm]],表示创建该函数所在 Realm 的 Realm Record。
  • [[InitialName]],作为函数初始名称的 String。它由 20.2.3.5 使用。
  • [[Async]],一个 Boolean,指示该函数在 BuiltinCallOrConstruct 中是否具有异步函数调用和构造行为。

除非另有规定,内置函数对象的 [[Prototype]] 内部槽的初始值为 %Function.prototype%。

内置函数对象必须具有符合 10.3.1 中定义的 [[Call]] 内部方法。

当且仅当内置函数对象被描述为“构造函数”,或者本规范中的某个算法显式设置其 [[Construct]] 内部方法时,它才具有 [[Construct]] 内部方法。这样的 [[Construct]] 内部方法必须符合 10.3.2 中的定义。

实现可以提供本规范未定义的其他内置函数对象。

10.3.1 [[Call]] ( thisArg, argList )

a built-in function object func的内部方法 [[Call]],接收参数 thisArg (ECMAScript 语言值) 和 argList (列表 (元素:ECMAScript 语言值));返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 返回 ? BuiltinCallOrConstruct(func, thisArg, argList, undefined)。

10.3.2 [[Construct]] ( argList, newTarget )

a built-in function object func (when the method is present)的内部方法 [[Construct]],接收参数 argList (列表 (元素:ECMAScript 语言值)) 和 newTarget (构造函数);返回值:(正常完成 (值:Object) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 result 为 ? BuiltinCallOrConstruct(func, uninitialized, argList, newTarget)。
  2. 断言:result 是 Object。
  3. 返回 result。

10.3.3 BuiltinCallOrConstruct ( func, thisArg, argList, newTarget )

抽象操作 BuiltinCallOrConstruct,接收参数 func (内置函数对象)、thisArg ((ECMAScript 语言值 或 uninitialized))、argList (列表 (元素:ECMAScript 语言值)) 和 newTarget ((构造函数 或 undefined));返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 callerContext 为正在运行的执行上下文。
  2. 如果 callerContext 尚未暂停,则暂停 callerContext。
  3. 令 calleeContext 为新的执行上下文。
  4. 将 calleeContext 的 Function 设置为 func。
  5. 令 calleeRealm 为 func.[[Realm]]。
  6. 将 calleeContext 的 Realm 设置为 calleeRealm。
  7. 将 calleeContext 的 ScriptOrModule 设置为 null。
  8. 执行对 calleeContext 所需的任何实现定义初始化。
  9. 将 calleeContext 压入执行上下文栈;calleeContext 现在是正在运行的执行上下文。
  10. 如果 func.[[Async]] 是 true,则
    1. 令 promiseCapability 为 ! NewPromiseCapability(%Promise%)。
    2. 令 resultsClosure 为一个没有参数的新 Abstract Closure,它捕获 func、thisArg、argList 和 newTarget,并在被调用时执行以下步骤:
      1. 令 result 为按照符合 func 规范的方式对 func 求值的结果所得的 Completion Record。如果 thisArg 是 uninitialized,则 this 值未初始化;否则 thisArg 提供 this 值。argList 提供具名参数。newTarget 提供 NewTarget 值。
      2. 注:如果 func 在本文档中定义,则“func 的规范”是通过算法步骤或其他方式为它规定的行为。
      3. 返回 Completion(result)。
    3. 执行 AsyncFunctionStart(promiseCapability, resultsClosure)。
    4. 从执行上下文栈中移除 calleeContext,并恢复 callerContext 作为正在运行的执行上下文。
    5. 返回 promiseCapability.[[Promise]]。
  11. 令 result 为按照符合 func 规范的方式对 func 求值的结果所得的 Completion Record。如果 thisArg 是 uninitialized,则 this 值未初始化;否则 thisArg 提供 this 值。argList 提供具名参数。newTarget 提供 NewTarget 值。
  12. 注:如果 func 在本文档中定义,则“func 的规范”是通过算法步骤或其他方式为它规定的行为。
  13. 从执行上下文栈中移除 calleeContext,并恢复 callerContext 作为正在运行的执行上下文。
  14. 返回 ? result。
注

从执行上下文栈中移除 calleeContext 时,如果它已经暂停并由可访问的 Generator 保留以便以后恢复,则不得销毁它。

10.3.4 CreateBuiltinFunction ( behaviour, length, name, additionalInternalSlotsList [ , realm [ , proto [ , prefix [ , async ] ] ] ] )

抽象操作 CreateBuiltinFunction,接收参数 behaviour ((抽象闭包、a set of algorithm steps 或 some other definition of a function's behaviour provided in this specification))、length ((非负整数 或 +∞))、name ((属性键 或 私有名称)) 和 additionalInternalSlotsList (列表 (元素:内部槽名称))和可选参数 realm (Realm 记录)、proto ((Object 或 null))、prefix (String) 和 async (Boolean);返回值:内置函数对象。 additionalInternalSlotsList 包含必须作为对象一部分定义的附加内部槽名称。此操作创建一个内置函数对象。 调用时执行以下步骤:

  1. 如果不存在 realm,则将 realm 设置为当前 Realm Record。
  2. 如果不存在 proto,则将 proto 设置为 realm.[[Intrinsics]].[[%Function.prototype%]]。
  3. 如果不存在 async,则将 async 设置为 false。
  4. 令 internalSlotsList 为一个 List,其中包含 10.3 对即将创建的内置函数对象要求的所有内部槽名称。
  5. 将 additionalInternalSlotsList 的元素追加到 internalSlotsList。
  6. 令 func 为新的内置函数对象;当被调用时,它使用所提供的参数作为 behaviour 所规定对应参数的值,执行 behaviour 所描述的操作。新函数对象具有名称为 internalSlotsList 中元素的内部槽,以及一个 [[InitialName]] 内部槽。
  7. 将 func.[[Async]] 设置为 async。
  8. 将 func.[[Prototype]] 设置为 proto。
  9. 将 func.[[Extensible]] 设置为 true。
  10. 将 func.[[Realm]] 设置为 realm。
  11. 将 func.[[InitialName]] 设置为 null。
  12. 执行 SetFunctionLength(func, length)。
  13. 如果不存在 prefix,则
    1. 执行 SetFunctionName(func, name)。
  14. 否则,
    1. 执行 SetFunctionName(func, name, prefix)。
  15. 返回 func。

本规范中定义的每个内置函数都通过调用 CreateBuiltinFunction 抽象操作创建。

10.4 内置异质对象内部方法和内部槽

本规范定义了若干种内置异质对象。这些对象通常与普通对象行为类似,仅在少数特定情况下有所不同。以下异质对象除下文明确另有规定外,都使用普通对象内部方法:

10.4.1 绑定函数异质对象

绑定函数异质对象是一种包装另一个函数对象的异质对象。绑定函数异质对象是可调用的(它具有 [[Call]] 内部方法,并且可能具有 [[Construct]] 内部方法)。调用绑定函数异质对象通常会导致调用其所包装的函数。

如果一个对象的 [[Call]] 以及(如果适用)[[Construct]] 内部方法使用以下实现,并且其其他基本内部方法使用 10.1 中的定义,则该对象是绑定函数异质对象。这些方法在 BoundFunctionCreate 中安装。

绑定函数异质对象不具有 表 26 中列出的 ECMAScript 函数对象内部槽。相反,除 [[Prototype]] 和 [[Extensible]] 外,它们还具有 表 27 中列出的内部槽。

表 27: 绑定函数异质对象的内部槽
内部槽 类型 描述
[[BoundTargetFunction]] 可调用 Object 被包装的函数对象。
[[BoundThis]] ECMAScript 语言值 调用被包装函数时始终作为 this 值传递的值。
[[BoundArguments]] ECMAScript 语言值的 List 一个值列表,其元素用作对被包装函数的任何调用中的首批参数。

10.4.1.1 [[Call]] ( thisArg, argList )

a bound function exotic object func的内部方法 [[Call]],接收参数 thisArg (ECMAScript 语言值) 和 argList (列表 (元素:ECMAScript 语言值));返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 target 为 func.[[BoundTargetFunction]]。
  2. 令 boundThis 为 func.[[BoundThis]]。
  3. 令 boundArgs 为 func.[[BoundArguments]]。
  4. 令 args 为 boundArgs 和 argList 的列表连接。
  5. 返回 ? Call(target, boundThis, args)。

10.4.1.2 [[Construct]] ( argList, newTarget )

a bound function exotic object func的内部方法 [[Construct]],接收参数 argList (列表 (元素:ECMAScript 语言值)) 和 newTarget (构造函数);返回值:(正常完成 (值:Object) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 target 为 func.[[BoundTargetFunction]]。
  2. 断言:IsConstructor(target) 是 true。
  3. 令 boundArgs 为 func.[[BoundArguments]]。
  4. 令 args 为 boundArgs 和 argList 的列表连接。
  5. 如果 SameValue(func, newTarget) 是 true,则将 newTarget 设置为 target。
  6. 返回 ? Construct(target, args, newTarget)。

10.4.1.3 BoundFunctionCreate ( targetFunc, boundThis, boundArgs )

抽象操作 BoundFunctionCreate,接收参数 targetFunc (函数对象)、boundThis (ECMAScript 语言值) 和 boundArgs (列表 (元素:ECMAScript 语言值));返回值:(正常完成 (值:函数对象) 或 抛出完成)。 它用于规定创建新的绑定函数异质对象。 调用时执行以下步骤:

  1. 令 proto 为 ? targetFunc.[[GetPrototypeOf]]()。
  2. 令 internalSlotsList 为 « [[Prototype]], [[Extensible]] » 与 表 27 中列出的内部槽的列表连接。
  3. 令 obj 为 MakeBasicObject(internalSlotsList)。
  4. 将 obj.[[Prototype]] 设置为 proto。
  5. 按 10.4.1.1 中的规定设置 obj.[[Call]]。
  6. 如果 IsConstructor(targetFunc) 是 true,则
    1. 按 10.4.1.2 中的规定设置 obj.[[Construct]]。
  7. 将 obj.[[BoundTargetFunction]] 设置为 targetFunc。
  8. 将 obj.[[BoundThis]] 设置为 boundThis。
  9. 将 obj.[[BoundArguments]] 设置为 boundArgs。
  10. 返回 obj。

10.4.2 Array 异质对象

Array 是一种对数组索引属性键(参见 6.1.7)进行特殊处理的异质对象。属性名称为数组索引的属性也称为元素。每个 Array 都有一个不可配置的 "length" 属性,其值始终是数学值严格小于 232 的非负整数 Number。"length" 属性的值在数值上大于名称为数组索引的每个自有属性的名称;每当创建或更改 Array 的自有属性时,都会根据需要调整其他属性以维持此不变量。具体而言,每当添加名称为数组索引的自有属性时,如有必要,"length" 属性的值会更改为该数组索引数值加一;而每当 "length" 属性的值发生变化时,所有名称为数组索引且其值不小于新长度的自有属性都会被删除。此约束仅适用于 Array 的自有属性,不受可能从其原型继承的 "length" 或数组索引属性影响。

如果一个对象的 [[DefineOwnProperty]] 内部方法使用以下实现,并且其其他基本内部方法使用 10.1 中的定义,则该对象是 Array 异质对象(或简称 Array)。这些方法在 ArrayCreate 中安装。

10.4.2.1 [[DefineOwnProperty]] ( propertyKey, propertyDesc )

an Array exotic object array的内部方法 [[DefineOwnProperty]],接收参数 propertyKey (属性键) 和 propertyDesc (属性描述符);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 propertyKey 是 "length",则返回 ? ArraySetLength(array, propertyDesc)。
  2. 如果 propertyKey 是数组索引,则
    1. 令 lengthDesc 为 OrdinaryGetOwnProperty(array, "length")。
    2. 断言:lengthDesc 不是 undefined。
    3. 断言:IsDataDescriptor(lengthDesc) 是 true。
    4. 断言:lengthDesc.[[Configurable]] 是 false。
    5. 令 length 为 lengthDesc.[[Value]]。
    6. 断言:length 是非负整数 Number。
    7. 令 index 为 ! ToUint32(propertyKey)。
    8. 如果 index ≥ length 且 lengthDesc.[[Writable]] 是 false,则返回 false。
    9. 令 succeeded 为 ! OrdinaryDefineOwnProperty(array, propertyKey, propertyDesc)。
    10. 如果 succeeded 是 false,则返回 false。
    11. 如果 index ≥ length,则
      1. 将 lengthDesc.[[Value]] 设置为 index + 1𝔽。
      2. 将 succeeded 设置为 ! OrdinaryDefineOwnProperty(array, "length", lengthDesc)。
      3. 断言:succeeded 是 true。
    12. 返回 true。
  3. 返回 ? OrdinaryDefineOwnProperty(array, propertyKey, propertyDesc)。

10.4.2.2 ArrayCreate ( length [ , proto ] )

抽象操作 ArrayCreate,接收参数 length (非负整数)和可选参数 proto (Object);返回值:(正常完成 (值:Array 特异对象) 或 抛出完成)。 它用于规定创建新的 Array。 调用时执行以下步骤:

  1. 如果 length > 232 - 1,则抛出 RangeError 异常。
  2. 如果不存在 proto,则将 proto 设置为 %Array.prototype%。
  3. 令 array 为 MakeBasicObject(« [[Prototype]], [[Extensible]] »)。
  4. 将 array.[[Prototype]] 设置为 proto。
  5. 按 10.4.2.1 中的规定设置 array.[[DefineOwnProperty]]。
  6. 执行 ! OrdinaryDefineOwnProperty(array, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  7. 返回 array。

10.4.2.3 ArraySpeciesCreate ( originalArray, length )

抽象操作 ArraySpeciesCreate,接收参数 originalArray (Object) 和 length (非负整数);返回值:(正常完成 (值:Object) 或 抛出完成)。 它用于规定使用从 originalArray 派生的构造函数创建新的 Array 或类似对象。它并不强制要求该构造函数返回 Array。 调用时执行以下步骤:

  1. 令 isArray 为 ? IsArray(originalArray)。
  2. 如果 isArray 是 false,则返回 ? ArrayCreate(length)。
  3. 令 ctor 为 ? Get(originalArray, "constructor")。
  4. 如果 IsConstructor(ctor) 是 true,则
    1. 令 thisRealm 为当前 Realm Record。
    2. 令 ctorRealm 为 ? GetFunctionRealm(ctor)。
    3. 如果 thisRealm 和 ctorRealm 不是同一个 Realm Record,则
      1. 如果 SameValue(ctor, ctorRealm.[[Intrinsics]].[[%Array%]]) 是 true,则将 ctor 设置为 undefined。
  5. 如果 ctor 是 Object,则
    1. 将 ctor 设置为 ? Get(ctor, %Symbol.species%)。
    2. 如果 ctor 是 null,则将 ctor 设置为 undefined。
  6. 如果 ctor 是 undefined,则返回 ? ArrayCreate(length)。
  7. 如果 IsConstructor(ctor) 是 false,则抛出 TypeError 异常。
  8. 返回 ? Construct(ctor, « 𝔽(length) »)。
注

如果 originalArray 是使用并非正在运行的执行上下文所属 Realm 的标准内置 Array 构造函数创建的,则会使用正在运行的执行上下文所属 Realm 创建新的 Array。这维持了与 Web 浏览器历史行为的兼容性;那些现在使用 ArraySpeciesCreate 定义的 Array.prototype 方法历史上就具有这种行为。

10.4.2.4 ArraySetLength ( array, propertyDesc )

抽象操作 ArraySetLength,接收参数 array (Array) 和 propertyDesc (属性描述符);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 propertyDesc 没有 [[Value]] 字段,则
    1. 返回 ! OrdinaryDefineOwnProperty(array, "length", propertyDesc)。
  2. 令 newLengthDesc 为 propertyDesc 的副本。
  3. 令 newLength 为 ? ToUint32(propertyDesc.[[Value]])。
  4. 令 numberLength 为 ? ToNumber(propertyDesc.[[Value]])。
  5. 如果 SameValueZero(newLength, numberLength) 是 false,则抛出 RangeError 异常。
  6. 将 newLengthDesc.[[Value]] 设置为 newLength。
  7. 令 oldLengthDesc 为 OrdinaryGetOwnProperty(array, "length")。
  8. 断言:oldLengthDesc 不是 undefined。
  9. 断言:IsDataDescriptor(oldLengthDesc) 是 true。
  10. 断言:oldLengthDesc.[[Configurable]] 是 false。
  11. 令 oldLength 为 oldLengthDesc.[[Value]]。
  12. 如果 newLength ≥ oldLength,则
    1. 返回 ! OrdinaryDefineOwnProperty(array, "length", newLengthDesc)。
  13. 如果 oldLengthDesc.[[Writable]] 是 false,则返回 false。
  14. 如果 newLengthDesc 没有 [[Writable]] 字段或 newLengthDesc.[[Writable]] 是 true,则
    1. 令 newWritable 为 true。
  15. 否则,
    1. 注:将 [[Writable]] 特性设置为 false 会被延迟,以防某些元素无法删除。
    2. 令 newWritable 为 false。
    3. 将 newLengthDesc.[[Writable]] 设置为 true。
  16. 令 succeeded 为 ! OrdinaryDefineOwnProperty(array, "length", newLengthDesc)。
  17. 如果 succeeded 是 false,则返回 false。
  18. 对 array 的每个自有属性键 propertyKey,其中 propertyKey 是数组索引并且 ! ToUint32(propertyKey) ≥ newLength,按照数值索引降序执行
    1. 令 deleteSucceeded 为 ! array.[[Delete]](propertyKey)。
    2. 如果 deleteSucceeded 是 false,则
      1. 将 newLengthDesc.[[Value]] 设置为 ! ToUint32(propertyKey) + 1𝔽。
      2. 如果 newWritable 是 false,则将 newLengthDesc.[[Writable]] 设置为 false。
      3. 执行 ! OrdinaryDefineOwnProperty(array, "length", newLengthDesc)。
      4. 返回 false。
  19. 如果 newWritable 是 false,则
    1. 将 succeeded 设置为 ! OrdinaryDefineOwnProperty(array, "length", PropertyDescriptor { [[Writable]]: false })。
    2. 断言:succeeded 是 true。
  20. 返回 true。
注

在步骤 3 和 4 中,如果 propertyDesc.[[Value]] 是对象,则其 valueOf 方法会被调用两次。这是自本规范第 2版起就规定具有此效果的遗留行为。

10.4.3 String 异质对象

String 对象是一种封装 String 值并暴露与该 String 值的各个码元元素对应的虚拟整数索引数据属性的异质对象。String 异质对象始终具有名为 "length" 的数据属性,其值是所封装 String 值的长度。码元数据属性和 "length" 属性均不可写且不可配置。

如果一个对象的 [[GetOwnProperty]]、[[DefineOwnProperty]] 和 [[OwnPropertyKeys]] 内部方法使用以下实现,并且其其他基本内部方法使用 10.1 中的定义,则该对象是 String 异质对象(或简称 String 对象)。这些方法在 StringCreate 中安装。

String 异质对象具有与普通对象相同的内部槽。它们还具有 [[StringData]] 内部槽。

10.4.3.1 [[GetOwnProperty]] ( propertyKey )

a String exotic object string的内部方法 [[GetOwnProperty]],接收参数 propertyKey (属性键);返回值:正常完成 (值:(属性描述符 或 undefined))。 调用时执行以下步骤:

  1. 令 propertyDesc 为 OrdinaryGetOwnProperty(string, propertyKey)。
  2. 如果 propertyDesc 不是 undefined,则返回 propertyDesc。
  3. 返回 StringGetOwnProperty(string, propertyKey)。

10.4.3.2 [[DefineOwnProperty]] ( propertyKey, propertyDesc )

a String exotic object string的内部方法 [[DefineOwnProperty]],接收参数 propertyKey (属性键) 和 propertyDesc (属性描述符);返回值:正常完成 (值:Boolean)。 调用时执行以下步骤:

  1. 令 stringDesc 为 StringGetOwnProperty(string, propertyKey)。
  2. 如果 stringDesc 不是 undefined,则
    1. 令 extensible 为 string.[[Extensible]]。
    2. 返回 IsCompatiblePropertyDescriptor(extensible, propertyDesc, stringDesc)。
  3. 返回 ! OrdinaryDefineOwnProperty(string, propertyKey, propertyDesc)。

10.4.3.3 [[OwnPropertyKeys]] ( )

a String exotic object obj的内部方法 [[OwnPropertyKeys]],接收无参数;返回值:正常完成 (值:列表 (元素:属性键))。 调用时执行以下步骤:

  1. 令 keys 为新的空 List。
  2. 令 string 为 obj.[[StringData]]。
  3. 断言:string 是 String。
  4. 令 length 为 string 的长度。
  5. 对满足 0 ≤ i < length 的每个整数 i,按升序执行
    1. 将 ! ToString(𝔽(i)) 追加到 keys。
  6. 对 obj 的每个自有属性键 propertyKey,其中 propertyKey 是数组索引且 ! ToIntegerOrInfinity(propertyKey) ≥ length,按照数值索引升序执行
    1. 将 propertyKey 追加到 keys。
  7. 对 obj 的每个自有属性键 propertyKey,其中 propertyKey 是 String 且 propertyKey 不是数组索引,按照属性创建时间升序执行
    1. 将 propertyKey 追加到 keys。
  8. 对 obj 的每个自有属性键 propertyKey,其中 propertyKey 是 Symbol,按照属性创建时间升序执行
    1. 将 propertyKey 追加到 keys。
  9. 返回 keys。

10.4.3.4 StringCreate ( value, proto )

抽象操作 StringCreate,接收参数 value (String) 和 proto (Object);返回值:String 特异对象。 它用于规定创建新的 String 异质对象。 调用时执行以下步骤:

  1. 令 string 为 MakeBasicObject(« [[Prototype]], [[Extensible]], [[StringData]] »)。
  2. 将 string.[[Prototype]] 设置为 proto。
  3. 将 string.[[StringData]] 设置为 value。
  4. 按 10.4.3.1 中的规定设置 string.[[GetOwnProperty]]。
  5. 按 10.4.3.2 中的规定设置 string.[[DefineOwnProperty]]。
  6. 按 10.4.3.3 中的规定设置 string.[[OwnPropertyKeys]]。
  7. 令 length 为 value 的长度。
  8. 执行 ! DefinePropertyOrThrow(string, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false })。
  9. 返回 string。

10.4.3.5 StringGetOwnProperty ( string, propertyKey )

抽象操作 StringGetOwnProperty,接收参数 string (String 特异对象) 和 propertyKey (属性键);返回值:(属性描述符 或 undefined)。 调用时执行以下步骤:

  1. 如果 propertyKey 不是 String,则返回 undefined。
  2. 令 numericIndex 为 CanonicalNumericIndexString(propertyKey)。
  3. 如果 numericIndex 不是整数 Number,则返回 undefined。
  4. 如果 numericIndex 是 -0𝔽 或 numericIndex < -0𝔽,则返回 undefined。
  5. 令 stringData 为 string.[[StringData]]。
  6. 断言:stringData 是 String。
  7. 令 length 为 stringData 的长度。
  8. 如果 ℝ(numericIndex) ≥ length,则返回 undefined。
  9. 令 resultString 为 stringData 从 ℝ(numericIndex) 到 ℝ(numericIndex) + 1 的子字符串。
  10. 返回 PropertyDescriptor { [[Value]]: resultString, [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false }。

10.4.4 Arguments 异质对象

大多数 ECMAScript 函数都会向其代码提供 arguments 对象。根据函数定义的特征,其 arguments 对象可能是普通对象,也可能是 arguments 异质对象。arguments 异质对象是一种异质对象,其数组索引属性映射到与其关联的 ECMAScript 函数调用的形式参数绑定。

如果一个对象的内部方法使用以下实现,而此处未规定的那些内部方法使用 10.1 中的定义,则该对象是 arguments 异质对象。这些方法在 CreateMappedArgumentsObject 中安装。

注 1

尽管 CreateUnmappedArgumentsObject 被归入本条款,但它创建的是普通对象,而不是 arguments 异质对象。

Arguments 异质对象具有与普通对象相同的内部槽。它们还具有 [[ParameterMap]] 内部槽。普通 arguments 对象也具有 [[ParameterMap]] 内部槽,其值始终为 undefined。对于普通 arguments 对象,[[ParameterMap]] 内部槽仅由 Object.prototype.toString(20.1.3.6)使用,以将其识别为 arguments 对象。

注 2

arguments 异质对象中数值名称小于相应函数对象形式参数数量的整数索引数据属性,最初会与函数执行上下文中对应参数绑定共享其值。这意味着更改属性会更改参数绑定的对应值,反之亦然。如果删除此类属性后重新定义,或者将该属性更改为访问器属性,这种对应关系就会被解除。如果 arguments 对象是普通对象,则其属性值只是传给函数的参数副本,属性值与形式参数值之间不存在动态链接。

注 3

ParameterMap 对象及其属性值被用作规定 arguments 对象与参数绑定之间对应关系的机制。ECMAScript 代码无法直接观察 ParameterMap 对象以及作为其属性值的对象。ECMAScript 实现无需实际创建或使用此类对象即可实现规定的语义。

注 4

普通 arguments 对象定义了一个名为 "callee" 的不可配置访问器属性,访问该属性会抛出 TypeError 异常。"callee" 属性对于 arguments 异质对象具有更具体的含义,而 arguments 异质对象只会为某类非严格函数创建。普通变体中定义此属性,是为了确保符合规范的 ECMAScript 实现不会以其他方式定义它。

注 5

ECMAScript 对 arguments 异质对象的实现历史上曾包含一个名为 "caller" 的访问器属性。在 ECMAScript 2017 之前,本规范包含了普通 arguments 对象上会抛出异常的 "caller" 属性定义。由于实现不再包含此扩展,ECMAScript 2017 取消了会抛出异常的 "caller" 访问器要求。

10.4.4.1 [[GetOwnProperty]] ( propertyKey )

an arguments exotic object args的内部方法 [[GetOwnProperty]],接收参数 propertyKey (属性键);返回值:正常完成 (值:(属性描述符 或 undefined))。 调用时执行以下步骤:

  1. 令 propertyDesc 为 OrdinaryGetOwnProperty(args, propertyKey)。
  2. 如果 propertyDesc 是 undefined,则返回 undefined。
  3. 令 map 为 args.[[ParameterMap]]。
  4. 令 isMapped 为 ! HasOwnProperty(map, propertyKey)。
  5. 如果 isMapped 是 true,则
    1. 将 propertyDesc.[[Value]] 设置为 ! Get(map, propertyKey)。
  6. 返回 propertyDesc。

10.4.4.2 [[DefineOwnProperty]] ( propertyKey, propertyDesc )

an arguments exotic object args的内部方法 [[DefineOwnProperty]],接收参数 propertyKey (属性键) 和 propertyDesc (属性描述符);返回值:正常完成 (值:Boolean)。 调用时执行以下步骤:

  1. 令 map 为 args.[[ParameterMap]]。
  2. 令 isMapped 为 ! HasOwnProperty(map, propertyKey)。
  3. 令 newArgDesc 为 propertyDesc。
  4. 如果 isMapped 是 true 且 IsDataDescriptor(propertyDesc) 是 true,则
    1. 如果 propertyDesc 没有 [[Value]] 字段、propertyDesc 具有 [[Writable]] 字段并且 propertyDesc.[[Writable]] 是 false,则
      1. 将 newArgDesc 设置为 propertyDesc 的副本。
      2. 将 newArgDesc.[[Value]] 设置为 ! Get(map, propertyKey)。
  5. 令 allowed 为 ! OrdinaryDefineOwnProperty(args, propertyKey, newArgDesc)。
  6. 如果 allowed 是 false,则返回 false。
  7. 如果 isMapped 是 true,则
    1. 如果 IsAccessorDescriptor(propertyDesc) 是 true,则
      1. 执行 ! map.[[Delete]](propertyKey)。
    2. 否则,
      1. 如果 propertyDesc 具有 [[Value]] 字段,则
        1. 断言:以下 Set 将会成功,因为由 arguments 对象映射的形式参数始终可写。
        2. 执行 ! Set(map, propertyKey, propertyDesc.[[Value]], false)。
      2. 如果 propertyDesc 具有 [[Writable]] 字段且 propertyDesc.[[Writable]] 是 false,则
        1. 执行 ! map.[[Delete]](propertyKey)。
  8. 返回 true。

10.4.4.3 [[Get]] ( propertyKey, receiver )

an arguments exotic object args的内部方法 [[Get]],接收参数 propertyKey (属性键) 和 receiver (ECMAScript 语言值);返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 map 为 args.[[ParameterMap]]。
  2. 令 isMapped 为 ! HasOwnProperty(map, propertyKey)。
  3. 如果 isMapped 是 false,则返回 ? OrdinaryGet(args, propertyKey, receiver)。
  4. 断言:map 包含 propertyKey 的形式参数映射。
  5. 返回 ! Get(map, propertyKey)。

10.4.4.4 [[Set]] ( propertyKey, value, receiver )

an arguments exotic object args的内部方法 [[Set]],接收参数 propertyKey (属性键)、value (ECMAScript 语言值) 和 receiver (ECMAScript 语言值);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 SameValue(args, receiver) 是 false,则
    1. 令 isMapped 为 false。
  2. 否则,
    1. 令 map 为 args.[[ParameterMap]]。
    2. 令 isMapped 为 ! HasOwnProperty(map, propertyKey)。
  3. 如果 isMapped 是 true,则
    1. 断言:以下 Set 将会成功,因为由 arguments 对象映射的形式参数始终可写。
    2. 执行 ! Set(map, propertyKey, value, false)。
  4. 返回 ? OrdinarySet(args, propertyKey, value, receiver)。

10.4.4.5 [[Delete]] ( propertyKey )

an arguments exotic object args的内部方法 [[Delete]],接收参数 propertyKey (属性键);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 map 为 args.[[ParameterMap]]。
  2. 令 isMapped 为 ! HasOwnProperty(map, propertyKey)。
  3. 令 result 为 ? OrdinaryDelete(args, propertyKey)。
  4. 如果 result 是 true 且 isMapped 是 true,则
    1. 执行 ! map.[[Delete]](propertyKey)。
  5. 返回 result。

10.4.4.6 CreateUnmappedArgumentsObject ( argList )

抽象操作 CreateUnmappedArgumentsObject,接收参数 argList (列表 (元素:ECMAScript 语言值));返回值:普通对象。 调用时执行以下步骤:

  1. 令 length 为 argList 中的元素数量。
  2. 令 obj 为 OrdinaryObjectCreate(%Object.prototype%, « [[ParameterMap]] »)。
  3. 将 obj.[[ParameterMap]] 设置为 undefined。
  4. 执行 ! DefinePropertyOrThrow(obj, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true })。
  5. 令 index 为 0。
  6. 当 index < length 时,重复执行,
    1. 令 value 为 argList[index]。
    2. 执行 ! CreateDataPropertyOrThrow(obj, ! ToString(𝔽(index)), value)。
    3. 将 index 设置为 index + 1。
  7. 执行 ! DefinePropertyOrThrow(obj, %Symbol.iterator%, PropertyDescriptor { [[Value]]: %Array.prototype.values%, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true })。
  8. 执行 ! DefinePropertyOrThrow(obj, "callee", PropertyDescriptor { [[Getter]]: %ThrowTypeError%, [[Setter]]: %ThrowTypeError%, [[Enumerable]]: false, [[Configurable]]: false })。
  9. 返回 obj。

10.4.4.7 CreateMappedArgumentsObject ( func, formals, argList, envRecord )

抽象操作 CreateMappedArgumentsObject,接收参数 func (ECMAScript 函数对象)、formals (解析节点)、argList (列表 (元素:ECMAScript 语言值)) 和 envRecord (Environment 记录);返回值:arguments 特异对象。 调用时执行以下步骤:

  1. 断言:formals 不包含剩余参数、任何绑定模式或任何初始化器。它可以包含重复标识符。
  2. 令 length 为 argList 中的元素数量。
  3. 令 obj 为 MakeBasicObject(« [[Prototype]], [[Extensible]], [[ParameterMap]] »)。
  4. 按 10.4.4.1 中的规定设置 obj.[[GetOwnProperty]]。
  5. 按 10.4.4.2 中的规定设置 obj.[[DefineOwnProperty]]。
  6. 按 10.4.4.3 中的规定设置 obj.[[Get]]。
  7. 按 10.4.4.4 中的规定设置 obj.[[Set]]。
  8. 按 10.4.4.5 中的规定设置 obj.[[Delete]]。
  9. 将 obj.[[Prototype]] 设置为 %Object.prototype%。
  10. 令 map 为 OrdinaryObjectCreate(null)。
  11. 将 obj.[[ParameterMap]] 设置为 map。
  12. 令 paramNames 为 formals 的 BoundNames。
  13. 令 paramCount 为 paramNames 中的元素数量。
  14. 令 index 为 0。
  15. 当 index < length 时,重复执行,
    1. 令 value 为 argList[index]。
    2. 执行 ! CreateDataPropertyOrThrow(obj, ! ToString(𝔽(index)), value)。
    3. 将 index 设置为 index + 1。
  16. 执行 ! DefinePropertyOrThrow(obj, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true })。
  17. 令 mappedNames 为新的空 List。
  18. 将 index 设置为 paramCount - 1。
  19. 当 index ≥ 0 时,重复执行,
    1. 令 name 为 paramNames[index]。
    2. 如果 mappedNames 不包含 name,则
      1. 将 name 追加到 mappedNames。
      2. 如果 index < length,则
        1. 令 getter 为 MakeArgGetter(name, envRecord)。
        2. 令 setter 为 MakeArgSetter(name, envRecord)。
        3. 执行 ! map.[[DefineOwnProperty]](! ToString(𝔽(index)), PropertyDescriptor { [[Setter]]: setter, [[Getter]]: getter, [[Enumerable]]: false, [[Configurable]]: true })。
    3. 将 index 设置为 index - 1。
  20. 执行 ! DefinePropertyOrThrow(obj, %Symbol.iterator%, PropertyDescriptor { [[Value]]: %Array.prototype.values%, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true })。
  21. 执行 ! DefinePropertyOrThrow(obj, "callee", PropertyDescriptor { [[Value]]: func, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true })。
  22. 返回 obj。

10.4.4.7.1 MakeArgGetter ( name, envRecord )

抽象操作 MakeArgGetter,接收参数 name (String) 和 envRecord (Environment 记录);返回值:函数对象。 它创建一个内置函数对象,该对象在执行时返回 envRecord 中绑定到 name 的值。 调用时执行以下步骤:

  1. 令 getterClosure 为一个没有参数的新 Abstract Closure,它捕获 name 和 envRecord,并在被调用时执行以下步骤:
    1. 返回 NormalCompletion(! envRecord.GetBindingValue(name, false))。
  2. 令 getter 为 CreateBuiltinFunction(getterClosure, 0, "", « »)。
  3. 注:ECMAScript 代码永远无法直接访问 getter。
  4. 返回 getter。

10.4.4.7.2 MakeArgSetter ( name, envRecord )

抽象操作 MakeArgSetter,接收参数 name (String) 和 envRecord (Environment 记录);返回值:函数对象。 它创建一个内置函数对象,该对象在执行时设置 envRecord 中绑定到 name 的值。 调用时执行以下步骤:

  1. 令 setterClosure 为一个具有参数 (value) 的新 Abstract Closure,它捕获 name 和 envRecord,并在被调用时执行以下步骤:
    1. 返回 NormalCompletion(! envRecord.SetMutableBinding(name, value, false))。
  2. 令 setter 为 CreateBuiltinFunction(setterClosure, 1, "", « »)。
  3. 注:ECMAScript 代码永远无法直接访问 setter。
  4. 返回 setter。

10.4.5 TypedArray 异质对象

TypedArray 是一种对规范数值字符串形式的属性键进行特殊处理的异质对象:其中处于范围内的整数索引子集用于索引统一类型的元素,而其余属性则强制不存在,无需进行原型链遍历。

注

因为对于任意 Number n,ToString(n) 都是规范数值字符串,所以实现可以将 Number 作为 TypedArray 的属性键处理,而无需实际执行字符串转换。

TypedArray 具有与普通对象相同的内部槽,此外还具有 [[ViewedArrayBuffer]]、[[TypedArrayName]]、[[ContentType]]、[[ByteLength]]、[[ByteOffset]] 和 [[ArrayLength]] 内部槽。

如果一个对象的 [[PreventExtensions]]、[[GetOwnProperty]]、[[HasProperty]]、[[DefineOwnProperty]]、[[Get]]、[[Set]]、[[Delete]] 和 [[OwnPropertyKeys]] 内部方法使用本节中的定义,而其其他基本内部方法使用 10.1 中的定义,则该对象是 TypedArray。这些方法由 TypedArrayCreate 安装。

10.4.5.1 [[PreventExtensions]] ( )

a TypedArray obj的内部方法 [[PreventExtensions]],接收无参数;返回值:正常完成 (值:Boolean)。 调用时执行以下步骤:

  1. 注:6.1.7.3 中规定的可扩展性相关不变量不允许当 obj 能够获得(或失去后重新获得)属性时,此方法返回 true;当其底层缓冲区调整大小时,具有整数索引名称的属性可能会发生这种情况。
  2. 如果 IsTypedArrayFixedLength(obj) 是 false,则返回 false。
  3. 返回 OrdinaryPreventExtensions(obj)。

10.4.5.2 [[GetOwnProperty]] ( propertyKey )

a TypedArray obj的内部方法 [[GetOwnProperty]],接收参数 propertyKey (属性键);返回值:正常完成 (值:(属性描述符 或 undefined))。 调用时执行以下步骤:

  1. 如果 propertyKey 是 String,则
    1. 令 numericIndex 为 CanonicalNumericIndexString(propertyKey)。
    2. 如果 numericIndex 不是 undefined,则
      1. 令 value 为 TypedArrayGetElement(obj, numericIndex)。
      2. 如果 value 是 undefined,则返回 undefined。
      3. 返回 PropertyDescriptor { [[Value]]: value, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }。
  2. 返回 OrdinaryGetOwnProperty(obj, propertyKey)。

10.4.5.3 [[HasProperty]] ( propertyKey )

a TypedArray obj的内部方法 [[HasProperty]],接收参数 propertyKey (属性键);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 propertyKey 是 String,则
    1. 令 numericIndex 为 CanonicalNumericIndexString(propertyKey)。
    2. 如果 numericIndex 不是 undefined,则返回 IsValidIntegerIndex(obj, numericIndex)。
  2. 返回 ? OrdinaryHasProperty(obj, propertyKey)。

10.4.5.4 [[DefineOwnProperty]] ( propertyKey, propertyDesc )

a TypedArray obj的内部方法 [[DefineOwnProperty]],接收参数 propertyKey (属性键) 和 propertyDesc (属性描述符);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 propertyKey 是 String,则
    1. 令 numericIndex 为 CanonicalNumericIndexString(propertyKey)。
    2. 如果 numericIndex 不是 undefined,则
      1. 如果 IsValidIntegerIndex(obj, numericIndex) 是 false,则返回 false。
      2. 如果 propertyDesc 具有 [[Configurable]] 字段且 propertyDesc.[[Configurable]] 是 false,则返回 false。
      3. 如果 propertyDesc 具有 [[Enumerable]] 字段且 propertyDesc.[[Enumerable]] 是 false,则返回 false。
      4. 如果 IsAccessorDescriptor(propertyDesc) 是 true,则返回 false。
      5. 如果 propertyDesc 具有 [[Writable]] 字段且 propertyDesc.[[Writable]] 是 false,则返回 false。
      6. 如果 propertyDesc 具有 [[Value]] 字段,则执行 ? TypedArraySetElement(obj, numericIndex, propertyDesc.[[Value]])。
      7. 返回 true。
  2. 返回 ! OrdinaryDefineOwnProperty(obj, propertyKey, propertyDesc)。

10.4.5.5 [[Get]] ( propertyKey, receiver )

a TypedArray obj的内部方法 [[Get]],接收参数 propertyKey (属性键) 和 receiver (ECMAScript 语言值);返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 propertyKey 是 String,则
    1. 令 numericIndex 为 CanonicalNumericIndexString(propertyKey)。
    2. 如果 numericIndex 不是 undefined,则
      1. 返回 TypedArrayGetElement(obj, numericIndex)。
  2. 返回 ? OrdinaryGet(obj, propertyKey, receiver)。

10.4.5.6 [[Set]] ( propertyKey, value, receiver )

a TypedArray obj的内部方法 [[Set]],接收参数 propertyKey (属性键)、value (ECMAScript 语言值) 和 receiver (ECMAScript 语言值);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 propertyKey 是 String,则
    1. 令 numericIndex 为 CanonicalNumericIndexString(propertyKey)。
    2. 如果 numericIndex 不是 undefined,则
      1. 如果 SameValue(obj, receiver) 是 true,则
        1. 执行 ? TypedArraySetElement(obj, numericIndex, value)。
        2. 返回 true。
      2. 如果 IsValidIntegerIndex(obj, numericIndex) 是 false,则返回 true。
  2. 返回 ? OrdinarySet(obj, propertyKey, value, receiver)。

10.4.5.7 [[Delete]] ( propertyKey )

a TypedArray obj的内部方法 [[Delete]],接收参数 propertyKey (属性键);返回值:正常完成 (值:Boolean)。 调用时执行以下步骤:

  1. 如果 propertyKey 是 String,则
    1. 令 numericIndex 为 CanonicalNumericIndexString(propertyKey)。
    2. 如果 numericIndex 不是 undefined,则
      1. 如果 IsValidIntegerIndex(obj, numericIndex) 是 false,则返回 true。
      2. 返回 false。
  2. 返回 ! OrdinaryDelete(obj, propertyKey)。

10.4.5.8 [[OwnPropertyKeys]] ( )

a TypedArray obj的内部方法 [[OwnPropertyKeys]],接收无参数;返回值:正常完成 (值:列表 (元素:属性键))。 调用时执行以下步骤:

  1. 令 taRecord 为 MakeTypedArrayWithBufferWitnessRecord(obj, seq-cst)。
  2. 令 keys 为新的空 List。
  3. 如果 IsTypedArrayOutOfBounds(taRecord) 是 false,则
    1. 令 length 为 TypedArrayLength(taRecord)。
    2. 对满足 0 ≤ i < length 的每个整数 i,按升序执行
      1. 将 ! ToString(𝔽(i)) 追加到 keys。
  4. 对 obj 的每个自有属性键 propertyKey,其中 propertyKey 是 String 且 propertyKey 不是整数索引,按照属性创建时间升序执行
    1. 将 propertyKey 追加到 keys。
  5. 对 obj 的每个自有属性键 propertyKey,其中 propertyKey 是 Symbol,按照属性创建时间升序执行
    1. 将 propertyKey 追加到 keys。
  6. 返回 keys。

10.4.5.9 TypedArray With Buffer Witness Record

TypedArray With Buffer Witness Record 是用于封装 TypedArray 以及其所查看缓冲区的缓存字节长度的 Record。它用于帮助确保当所查看的缓冲区是可增长 SharedArrayBuffer 时,只对字节长度数据块产生一次 ReadSharedMemory 事件。

TypedArray With Buffer Witness Record 具有 表 28 中列出的字段。

表 28: TypedArray With Buffer Witness Record 字段
字段名称 值 含义
[[Object]] TypedArray 加载其缓冲区字节长度的 TypedArray。
[[CachedBufferByteLength]] 非负整数或 detached 创建该 Record 时对象的 [[ViewedArrayBuffer]] 的字节长度。

10.4.5.10 MakeTypedArrayWithBufferWitnessRecord ( obj, order )

抽象操作 MakeTypedArrayWithBufferWitnessRecord,接收参数 obj (TypedArray) 和 order ((seq-cst 或 unordered));返回值:TypedArray With Buffer Witness 记录。 调用时执行以下步骤:

  1. 令 buffer 为 obj.[[ViewedArrayBuffer]]。
  2. 如果 IsDetachedBuffer(buffer) 是 true,则
    1. 令 byteLength 为 detached。
  3. 否则,
    1. 令 byteLength 为 ArrayBufferByteLength(buffer, order)。
  4. 返回 TypedArray With Buffer Witness Record { [[Object]]: obj, [[CachedBufferByteLength]]: byteLength }。

10.4.5.11 TypedArrayCreate ( proto )

抽象操作 TypedArrayCreate,接收参数 proto (Object);返回值:TypedArray。 它用于规定创建新的 TypedArray。 调用时执行以下步骤:

  1. 令 internalSlotsList 为 « [[Prototype]], [[Extensible]], [[ViewedArrayBuffer]], [[TypedArrayName]], [[ContentType]], [[ByteLength]], [[ByteOffset]], [[ArrayLength]] »。
  2. 令 ta 为 MakeBasicObject(internalSlotsList)。
  3. 按 10.4.5.1 中的规定设置 ta.[[PreventExtensions]]。
  4. 按 10.4.5.2 中的规定设置 ta.[[GetOwnProperty]]。
  5. 按 10.4.5.3 中的规定设置 ta.[[HasProperty]]。
  6. 按 10.4.5.4 中的规定设置 ta.[[DefineOwnProperty]]。
  7. 按 10.4.5.5 中的规定设置 ta.[[Get]]。
  8. 按 10.4.5.6 中的规定设置 ta.[[Set]]。
  9. 按 10.4.5.7 中的规定设置 ta.[[Delete]]。
  10. 按 10.4.5.8 中的规定设置 ta.[[OwnPropertyKeys]]。
  11. 将 ta.[[Prototype]] 设置为 proto。
  12. 返回 ta。

10.4.5.12 TypedArrayByteLength ( taRecord )

抽象操作 TypedArrayByteLength,接收参数 taRecord (TypedArray With Buffer Witness 记录);返回值:非负整数。 调用时执行以下步骤:

  1. 断言:IsTypedArrayOutOfBounds(taRecord) 是 false。
  2. 令 obj 为 taRecord.[[Object]]。
  3. 如果 obj.[[ByteLength]] 不是 auto,则返回 obj.[[ByteLength]]。
  4. 令 length 为 TypedArrayLength(taRecord)。
  5. 令 elementSize 为 TypedArrayElementSize(obj)。
  6. 注:即使底层缓冲区已调整为非 elementSize 整数倍的大小,返回的字节长度也始终是 elementSize 的整数倍。
  7. 返回 length × elementSize。

10.4.5.13 TypedArrayLength ( taRecord )

抽象操作 TypedArrayLength,接收参数 taRecord (TypedArray With Buffer Witness 记录);返回值:非负整数。 调用时执行以下步骤:

  1. 断言:IsTypedArrayOutOfBounds(taRecord) 是 false。
  2. 令 obj 为 taRecord.[[Object]]。
  3. 如果 obj.[[ArrayLength]] 不是 auto,则返回 obj.[[ArrayLength]]。
  4. 断言:IsFixedLengthArrayBuffer(obj.[[ViewedArrayBuffer]]) 是 false。
  5. 令 byteOffset 为 obj.[[ByteOffset]]。
  6. 令 elementSize 为 TypedArrayElementSize(obj)。
  7. 令 byteLength 为 taRecord.[[CachedBufferByteLength]]。
  8. 断言:byteLength 不是 detached。
  9. 返回 floor((byteLength - byteOffset) / elementSize)。

10.4.5.14 IsTypedArrayOutOfBounds ( taRecord )

抽象操作 IsTypedArrayOutOfBounds,接收参数 taRecord (TypedArray With Buffer Witness 记录);返回值:Boolean。 它检查对象的任何数值属性是否引用底层缓冲区边界之外索引处的值。 调用时执行以下步骤:

  1. 令 obj 为 taRecord.[[Object]]。
  2. 令 bufferByteLength 为 taRecord.[[CachedBufferByteLength]]。
  3. 如果 IsDetachedBuffer(obj.[[ViewedArrayBuffer]]) 是 true,则
    1. 断言:bufferByteLength 是 detached。
    2. 返回 true。
  4. 断言:bufferByteLength 是非负整数。
  5. 令 byteOffsetStart 为 obj.[[ByteOffset]]。
  6. 如果 obj.[[ArrayLength]] 是 auto,则
    1. 令 byteOffsetEnd 为 bufferByteLength。
  7. 否则,
    1. 令 elementSize 为 TypedArrayElementSize(obj)。
    2. 令 arrayByteLength 为 obj.[[ArrayLength]] × elementSize。
    3. 令 byteOffsetEnd 为 byteOffsetStart + arrayByteLength。
  8. 注:[[ByteOffset]] 等于 bufferByteLength 的 0 长度 TypedArray 不视为越界。
  9. 如果 byteOffsetStart > bufferByteLength 或 byteOffsetEnd > bufferByteLength,则返回 true。
  10. 返回 false。

10.4.5.15 IsTypedArrayFixedLength ( obj )

抽象操作 IsTypedArrayFixedLength,接收参数 obj (TypedArray);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 obj.[[ArrayLength]] 是 auto,则返回 false。
  2. 令 buffer 为 obj.[[ViewedArrayBuffer]]。
  3. 如果 IsFixedLengthArrayBuffer(buffer) 是 false 且 IsSharedArrayBuffer(buffer) 是 false,则返回 false。
  4. 返回 true。

10.4.5.16 IsValidIntegerIndex ( obj, index )

抽象操作 IsValidIntegerIndex,接收参数 obj (TypedArray) 和 index (Number);返回值:Boolean。 调用时执行以下步骤:

  1. 如果 IsDetachedBuffer(obj.[[ViewedArrayBuffer]]) 是 true,则返回 false。
  2. 如果 index 不是整数 Number,则返回 false。
  3. 如果 index 是 -0𝔽 或 index < -0𝔽,则返回 false。
  4. 令 taRecord 为 MakeTypedArrayWithBufferWitnessRecord(obj, unordered)。
  5. 注:当 obj 的后备缓冲区是可增长 SharedArrayBuffer 时,边界检查不是同步操作。
  6. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,则返回 false。
  7. 令 length 为 TypedArrayLength(taRecord)。
  8. 如果 ℝ(index) ≥ length,则返回 false。
  9. 返回 true。

10.4.5.17 TypedArrayGetElement ( obj, index )

抽象操作 TypedArrayGetElement,接收参数 obj (TypedArray) 和 index (Number);返回值:(Number、BigInt 或 undefined)。 调用时执行以下步骤:

  1. 如果 IsValidIntegerIndex(obj, index) 是 false,则返回 undefined。
  2. 令 offset 为 obj.[[ByteOffset]]。
  3. 令 elementSize 为 TypedArrayElementSize(obj)。
  4. 令 byteIndexInBuffer 为 (ℝ(index) × elementSize) + offset。
  5. 令 elementType 为 TypedArrayElementType(obj)。
  6. 返回 GetValueFromBuffer(obj.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, true, unordered)。

10.4.5.18 TypedArraySetElement ( obj, index, value )

抽象操作 TypedArraySetElement,接收参数 obj (TypedArray)、index (Number) 和 value (ECMAScript 语言值);返回值:(正常完成 (值:unused) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 obj.[[ContentType]] 是 bigint,则令 number 为 ? ToBigInt(value)。
  2. 否则,令 number 为 ? ToNumber(value)。
  3. 如果 IsValidIntegerIndex(obj, index) 是 true,则
    1. 令 offset 为 obj.[[ByteOffset]]。
    2. 令 elementSize 为 TypedArrayElementSize(obj)。
    3. 令 byteIndexInBuffer 为 (ℝ(index) × elementSize) + offset。
    4. 令 elementType 为 TypedArrayElementType(obj)。
    5. 执行 SetValueInBuffer(obj.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, number, true, unordered)。
  4. 返回 unused。
注

此操作始终表现为成功,但当尝试写入超过 TypedArray 末尾的位置,或写入由已分离 ArrayBuffer 支持的 TypedArray 时,它不会产生任何效果。

10.4.5.19 IsArrayBufferViewOutOfBounds ( obj )

抽象操作 IsArrayBufferViewOutOfBounds,接收参数 obj ((TypedArray 或 DataView));返回值:Boolean。 它检查 TypedArray 的任何数值属性或 DataView 对象的方法是否能够引用底层数据块边界之外索引处的值。此抽象操作是为了方便上游规范而存在的。 调用时执行以下步骤:

  1. 如果 obj 具有 [[DataView]] 内部槽,则
    1. 令 viewRecord 为 MakeDataViewWithBufferWitnessRecord(obj, seq-cst)。
    2. 返回 IsViewOutOfBounds(viewRecord)。
  2. 令 taRecord 为 MakeTypedArrayWithBufferWitnessRecord(obj, seq-cst)。
  3. 返回 IsTypedArrayOutOfBounds(taRecord)。

10.4.6 模块命名空间异质对象

模块命名空间异质对象是一种暴露从 ECMAScript Module 导出的绑定的异质对象(参见 16.2.3)。模块命名空间异质对象的 String 键自有属性与 Module 导出的绑定名称之间存在一一对应关系。导出的绑定包括使用 export * 导出项间接导出的任何绑定。每个 String 值自有属性键都是对应导出绑定名称的 StringValue。这些是模块命名空间异质对象仅有的 String 键属性。每个此类属性都具有特性 { [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: false }。模块命名空间异质对象不可扩展。

如果一个对象的 [[GetPrototypeOf]]、[[SetPrototypeOf]]、[[IsExtensible]]、[[PreventExtensions]]、[[GetOwnProperty]]、[[DefineOwnProperty]]、[[HasProperty]]、[[Get]]、[[Set]]、[[Delete]] 和 [[OwnPropertyKeys]] 内部方法使用本节中的定义,而其其他基本内部方法使用 10.1 中的定义,则该对象是模块命名空间异质对象。这些方法由 ModuleNamespaceCreate 安装。

模块命名空间异质对象具有 表 29 中定义的内部槽。

表 29: 模块命名空间异质对象的内部槽
内部槽 类型 描述
[[Module]] Module Record 此命名空间所暴露导出的 Module Record。
[[Exports]] String 的 List 一个 List,其元素是作为此对象自有属性暴露的导出名称的 String 值。该列表按照码元字典序排序。

10.4.6.1 [[GetPrototypeOf]] ( )

a module namespace exotic object的内部方法 [[GetPrototypeOf]],接收无参数;返回值:正常完成 (值:null)。 调用时执行以下步骤:

  1. 返回 null。

10.4.6.2 [[SetPrototypeOf]] ( proto )

a module namespace exotic object obj的内部方法 [[SetPrototypeOf]],接收参数 proto ((Object 或 null));返回值:正常完成 (值:Boolean)。 调用时执行以下步骤:

  1. 返回 ! SetImmutablePrototype(obj, proto)。

10.4.6.3 [[IsExtensible]] ( )

a module namespace exotic object的内部方法 [[IsExtensible]],接收无参数;返回值:正常完成 (值:false)。 调用时执行以下步骤:

  1. 返回 false。

10.4.6.4 [[PreventExtensions]] ( )

a module namespace exotic object的内部方法 [[PreventExtensions]],接收无参数;返回值:正常完成 (值:true)。 调用时执行以下步骤:

  1. 返回 true。

10.4.6.5 [[GetOwnProperty]] ( propertyKey )

a module namespace exotic object obj的内部方法 [[GetOwnProperty]],接收参数 propertyKey (属性键);返回值:(正常完成 (值:(属性描述符 或 undefined)) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 propertyKey 是 Symbol,则返回 OrdinaryGetOwnProperty(obj, propertyKey)。
  2. 令 exports 为 obj.[[Exports]]。
  3. 如果 exports 不包含 propertyKey,则返回 undefined。
  4. 令 value 为 ? obj.[[Get]](propertyKey, obj)。
  5. 返回 PropertyDescriptor { [[Value]]: value, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: false }。

10.4.6.6 [[DefineOwnProperty]] ( propertyKey, propertyDesc )

a module namespace exotic object obj的内部方法 [[DefineOwnProperty]],接收参数 propertyKey (属性键) 和 propertyDesc (属性描述符);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 propertyKey 是 Symbol,则返回 ! OrdinaryDefineOwnProperty(obj, propertyKey, propertyDesc)。
  2. 令 current 为 ? obj.[[GetOwnProperty]](propertyKey)。
  3. 如果 current 是 undefined,则返回 false。
  4. 如果 propertyDesc 具有 [[Configurable]] 字段且 propertyDesc.[[Configurable]] 是 true,则返回 false。
  5. 如果 propertyDesc 具有 [[Enumerable]] 字段且 propertyDesc.[[Enumerable]] 是 false,则返回 false。
  6. 如果 IsAccessorDescriptor(propertyDesc) 是 true,则返回 false。
  7. 如果 propertyDesc 具有 [[Writable]] 字段且 propertyDesc.[[Writable]] 是 false,则返回 false。
  8. 如果 propertyDesc 具有 [[Value]] 字段,则返回 SameValue(propertyDesc.[[Value]], current.[[Value]])。
  9. 返回 true。

10.4.6.7 [[HasProperty]] ( propertyKey )

a module namespace exotic object obj的内部方法 [[HasProperty]],接收参数 propertyKey (属性键);返回值:正常完成 (值:Boolean)。 调用时执行以下步骤:

  1. 如果 propertyKey 是 Symbol,则返回 ! OrdinaryHasProperty(obj, propertyKey)。
  2. 令 exports 为 obj.[[Exports]]。
  3. 如果 exports 包含 propertyKey,则返回 true。
  4. 返回 false。

10.4.6.8 [[Get]] ( propertyKey, receiver )

a module namespace exotic object obj的内部方法 [[Get]],接收参数 propertyKey (属性键) 和 receiver (ECMAScript 语言值);返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 如果 propertyKey 是 Symbol,则
    1. 返回 ! OrdinaryGet(obj, propertyKey, receiver)。
  2. 令 exports 为 obj.[[Exports]]。
  3. 如果 exports 不包含 propertyKey,则返回 undefined。
  4. 令 module 为 obj.[[Module]]。
  5. 令 binding 为 module.ResolveExport(propertyKey)。
  6. 断言:binding 是 ResolvedBinding Record。
  7. 令 targetModule 为 binding.[[Module]]。
  8. 断言:targetModule 不是 undefined。
  9. 如果 binding.[[BindingName]] 是 namespace,则
    1. 返回 GetModuleNamespace(targetModule)。
  10. 令 targetEnv 为 targetModule.[[Environment]]。
  11. 如果 targetEnv 是 empty,则抛出 ReferenceError 异常。
  12. 返回 ? targetEnv.GetBindingValue(binding.[[BindingName]], true)。
注

ResolveExport 没有副作用。每次使用特定的 exportName、resolveSet 参数对调用此操作时,它都必须返回相同结果。实现可以选择预先计算或缓存每个模块命名空间异质对象 [[Exports]] 的 ResolveExport 结果。

10.4.6.9 [[Set]] ( propertyKey, value, receiver )

a module namespace exotic object的内部方法 [[Set]],接收参数 propertyKey (属性键)、value (ECMAScript 语言值) 和 receiver (ECMAScript 语言值);返回值:正常完成 (值:false)。 调用时执行以下步骤:

  1. 返回 false。

10.4.6.10 [[Delete]] ( propertyKey )

a module namespace exotic object obj的内部方法 [[Delete]],接收参数 propertyKey (属性键);返回值:正常完成 (值:Boolean)。 调用时执行以下步骤:

  1. 如果 propertyKey 是 Symbol,则
    1. 返回 ! OrdinaryDelete(obj, propertyKey)。
  2. 令 exports 为 obj.[[Exports]]。
  3. 如果 exports 包含 propertyKey,则返回 false。
  4. 返回 true。

10.4.6.11 [[OwnPropertyKeys]] ( )

a module namespace exotic object obj的内部方法 [[OwnPropertyKeys]],接收无参数;返回值:正常完成 (值:列表 (元素:属性键))。 调用时执行以下步骤:

  1. 令 exports 为 obj.[[Exports]]。
  2. 令 symbolKeys 为 OrdinaryOwnPropertyKeys(obj)。
  3. 返回 exports 和 symbolKeys 的列表连接。

10.4.6.12 ModuleNamespaceCreate ( module, exports )

抽象操作 ModuleNamespaceCreate,接收参数 module (Module 记录) 和 exports (列表 (元素:String));返回值:module namespace 特异对象。 它用于规定创建新的模块命名空间异质对象。 调用时执行以下步骤:

  1. 断言:module.[[Namespace]] 是 empty。
  2. 令 internalSlotsList 为 表 29 中列出的内部槽。
  3. 令 namespace 为 MakeBasicObject(internalSlotsList)。
  4. 将 namespace 的基本内部方法设置为 10.4.6 中规定的定义。
  5. 将 namespace.[[Module]] 设置为 module。
  6. 令 sortedExports 为一个 List,其元素是 exports 的元素,并按照码元字典序排序。
  7. 将 namespace.[[Exports]] 设置为 sortedExports。
  8. 创建 namespace 的自有属性,对应 28.3 中的定义。
  9. 将 module.[[Namespace]] 设置为 namespace。
  10. 返回 namespace。

10.4.7 不可变原型异质对象

不可变原型异质对象是一种异质对象,它具有 [[Prototype]] 内部槽,一旦初始化后就不会再改变。

如果一个对象的 [[SetPrototypeOf]] 内部方法使用以下实现,则该对象是不可变原型异质对象。(其其他基本内部方法可以根据具体不可变原型异质对象使用任意实现。)

注

与其他异质对象不同,不可变原型异质对象没有专门提供的创建抽象操作。这是因为它们仅由 %Object.prototype% 和宿主环境使用,而在宿主环境中,相关对象可能在其他方面也是异质的,因此需要各自专用的创建操作。

10.4.7.1 [[SetPrototypeOf]] ( proto )

an immutable prototype exotic object obj的内部方法 [[SetPrototypeOf]],接收参数 proto ((Object 或 null));返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 返回 ? SetImmutablePrototype(obj, proto)。

10.4.7.2 SetImmutablePrototype ( obj, proto )

抽象操作 SetImmutablePrototype,接收参数 obj (Object) 和 proto ((Object 或 null));返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 令 current 为 ? obj.[[GetPrototypeOf]]()。
  2. 如果 SameValue(proto, current) 是 true,则返回 true。
  3. 返回 false。

10.5 Proxy 对象内部方法和内部槽

Proxy 对象是一种异质对象,其基本内部方法部分使用 ECMAScript 代码实现。每个 Proxy 对象都有一个名为 [[ProxyHandler]] 的内部槽。[[ProxyHandler]] 的值是一个对象(称为代理的处理器对象)或 null。处理器对象的方法(参见 表 30)可用于增强一个或多个 Proxy 对象内部方法的实现。每个 Proxy 对象还有一个名为 [[ProxyTarget]] 的内部槽,其值为对象或 null。该对象称为代理的目标对象。

如果一个对象的基本内部方法(包括适用时的 [[Call]] 和 [[Construct]])使用本节中的定义,则该对象是 Proxy 异质对象。这些内部方法在 ProxyCreate 中安装。

表 30: Proxy 处理器方法
内部方法 处理器方法
[[GetPrototypeOf]] getPrototypeOf
[[SetPrototypeOf]] setPrototypeOf
[[IsExtensible]] isExtensible
[[PreventExtensions]] preventExtensions
[[GetOwnProperty]] getOwnPropertyDescriptor
[[DefineOwnProperty]] defineProperty
[[HasProperty]] has
[[Get]] get
[[Set]] set
[[Delete]] deleteProperty
[[OwnPropertyKeys]] ownKeys
[[Call]] apply
[[Construct]] construct

当调用处理器方法来提供 Proxy 对象内部方法的实现时,会将代理的目标对象作为参数传给处理器方法。代理的处理器对象不一定具有对应每个基本内部方法的方法。如果处理器对象没有对应内部陷阱的方法,则调用代理上的内部方法会导致调用代理目标对象上的相应内部方法。

Proxy 对象的 [[ProxyHandler]] 和 [[ProxyTarget]] 内部槽在对象创建时始终会被初始化,并且通常不可修改。某些 Proxy 对象以允许随后被撤销的方式创建。当代理被撤销时,其 [[ProxyHandler]] 和 [[ProxyTarget]] 内部槽会设置为 null,从而导致随后对该 Proxy 对象调用内部方法时抛出 TypeError 异常。

由于 Proxy 对象允许由任意 ECMAScript 代码提供内部方法的实现,因此可以定义处理器方法违反 6.1.7.3 中定义不变量的 Proxy 对象。6.1.7.3 中定义的一些内部方法不变量是基本完整性不变量。这些不变量由本节规定的 Proxy 对象内部方法显式强制执行。ECMAScript 实现必须能够稳健地处理所有可能的不变量违反情况。

在以下算法描述中,假定 obj 是 ECMAScript Proxy 对象,propertyKey 是属性键值,value 是任意 ECMAScript 语言值,而 propertyDesc 是 Property Descriptor Record。

10.5.1 [[GetPrototypeOf]] ( )

a Proxy exotic object obj的内部方法 [[GetPrototypeOf]],接收无参数;返回值:(正常完成 (值:(Object 或 null)) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. 令 target 为 obj.[[ProxyTarget]]。
  3. 令 handler 为 obj.[[ProxyHandler]]。
  4. 断言:handler 是 Object。
  5. 令 trap 为 ? GetMethod(handler, "getPrototypeOf")。
  6. 如果 trap 是 undefined,则
    1. 返回 ? target.[[GetPrototypeOf]]()。
  7. 令 handlerProto 为 ? Call(trap, handler, « target »)。
  8. 如果 handlerProto 不是 Object 且 handlerProto 不是 null,则抛出 TypeError 异常。
  9. 令 extensibleTarget 为 ? IsExtensible(target)。
  10. 如果 extensibleTarget 是 true,则返回 handlerProto。
  11. 令 targetProto 为 ? target.[[GetPrototypeOf]]()。
  12. 如果 SameValue(handlerProto, targetProto) 是 false,则抛出 TypeError 异常。
  13. 返回 handlerProto。
注

Proxy 对象的 [[GetPrototypeOf]] 强制执行以下不变量:

  • [[GetPrototypeOf]] 的结果必须是 Object 或 null。
  • 如果目标对象不可扩展,则应用于 Proxy 对象的 [[GetPrototypeOf]] 必须返回与应用于 Proxy 对象目标对象的 [[GetPrototypeOf]] 相同的值。

10.5.2 [[SetPrototypeOf]] ( proto )

a Proxy exotic object obj的内部方法 [[SetPrototypeOf]],接收参数 proto ((Object 或 null));返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. 令 target 为 obj.[[ProxyTarget]]。
  3. 令 handler 为 obj.[[ProxyHandler]]。
  4. 断言:handler 是 Object。
  5. 令 trap 为 ? GetMethod(handler, "setPrototypeOf")。
  6. 如果 trap 是 undefined,则
    1. 返回 ? target.[[SetPrototypeOf]](proto)。
  7. 令 boolTrapResult 为 ToBoolean(? Call(trap, handler, « target, proto »))。
  8. 如果 boolTrapResult 是 false,则返回 false。
  9. 令 extensibleTarget 为 ? IsExtensible(target)。
  10. 如果 extensibleTarget 是 true,则返回 true。
  11. 令 targetProto 为 ? target.[[GetPrototypeOf]]()。
  12. 如果 SameValue(proto, targetProto) 是 false,则抛出 TypeError 异常。
  13. 返回 true。
注

Proxy 对象的 [[SetPrototypeOf]] 强制执行以下不变量:

  • [[SetPrototypeOf]] 的结果是 Boolean 值。
  • 如果目标对象不可扩展,则参数值必须与应用于目标对象的 [[GetPrototypeOf]] 的结果相同。

10.5.3 [[IsExtensible]] ( )

a Proxy exotic object obj的内部方法 [[IsExtensible]],接收无参数;返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. 令 target 为 obj.[[ProxyTarget]]。
  3. 令 handler 为 obj.[[ProxyHandler]]。
  4. 断言:handler 是 Object。
  5. 令 trap 为 ? GetMethod(handler, "isExtensible")。
  6. 如果 trap 是 undefined,则
    1. 返回 ? IsExtensible(target)。
  7. 令 boolTrapResult 为 ToBoolean(? Call(trap, handler, « target »))。
  8. 令 targetResult 为 ? IsExtensible(target)。
  9. 如果 boolTrapResult 不是 targetResult,则抛出 TypeError 异常。
  10. 返回 boolTrapResult。
注

Proxy 对象的 [[IsExtensible]] 强制执行以下不变量:

  • [[IsExtensible]] 的结果是 Boolean 值。
  • 应用于 Proxy 对象的 [[IsExtensible]] 必须返回与使用相同参数应用于 Proxy 对象目标对象的 [[IsExtensible]] 相同的值。

10.5.4 [[PreventExtensions]] ( )

a Proxy exotic object obj的内部方法 [[PreventExtensions]],接收无参数;返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. 令 target 为 obj.[[ProxyTarget]]。
  3. 令 handler 为 obj.[[ProxyHandler]]。
  4. 断言:handler 是 Object。
  5. 令 trap 为 ? GetMethod(handler, "preventExtensions")。
  6. 如果 trap 是 undefined,则
    1. 返回 ? target.[[PreventExtensions]]()。
  7. 令 boolTrapResult 为 ToBoolean(? Call(trap, handler, « target »))。
  8. 如果 boolTrapResult 是 true,则
    1. 令 extensibleTarget 为 ? IsExtensible(target)。
    2. 如果 extensibleTarget 是 true,则抛出 TypeError 异常。
  9. 返回 boolTrapResult。
注

Proxy 对象的 [[PreventExtensions]] 强制执行以下不变量:

  • [[PreventExtensions]] 的结果是 Boolean 值。
  • 仅当应用于 Proxy 对象目标对象的 [[IsExtensible]] 为 false 时,应用于 Proxy 对象的 [[PreventExtensions]] 才返回 true。

10.5.5 [[GetOwnProperty]] ( propertyKey )

a Proxy exotic object obj的内部方法 [[GetOwnProperty]],接收参数 propertyKey (属性键);返回值:(正常完成 (值:(属性描述符 或 undefined)) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. 令 target 为 obj.[[ProxyTarget]]。
  3. 令 handler 为 obj.[[ProxyHandler]]。
  4. 断言:handler 是 Object。
  5. 令 trap 为 ? GetMethod(handler, "getOwnPropertyDescriptor")。
  6. 如果 trap 是 undefined,则
    1. 返回 ? target.[[GetOwnProperty]](propertyKey)。
  7. 令 trapResultObj 为 ? Call(trap, handler, « target, propertyKey »)。
  8. 如果 trapResultObj 不是 Object 且 trapResultObj 不是 undefined,则抛出 TypeError 异常。
  9. 令 targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)。
  10. 如果 trapResultObj 是 undefined,则
    1. 如果 targetDesc 是 undefined,则返回 undefined。
    2. 如果 targetDesc.[[Configurable]] 是 false,则抛出 TypeError 异常。
    3. 令 extensibleTarget 为 ? IsExtensible(target)。
    4. 如果 extensibleTarget 是 false,则抛出 TypeError 异常。
    5. 返回 undefined。
  11. 令 extensibleTarget 为 ? IsExtensible(target)。
  12. 令 resultDesc 为 ? ToPropertyDescriptor(trapResultObj)。
  13. 执行 CompletePropertyDescriptor(resultDesc)。
  14. 令 valid 为 IsCompatiblePropertyDescriptor(extensibleTarget, resultDesc, targetDesc)。
  15. 如果 valid 是 false,则抛出 TypeError 异常。
  16. 如果 resultDesc.[[Configurable]] 是 false,则
    1. 如果 targetDesc 是 undefined 或 targetDesc.[[Configurable]] 是 true,则
      1. 抛出 TypeError 异常。
    2. 如果 resultDesc 具有 [[Writable]] 字段且 resultDesc.[[Writable]] 是 false,则
      1. 断言:targetDesc 具有 [[Writable]] 字段。
      2. 如果 targetDesc.[[Writable]] 是 true,则抛出 TypeError 异常。
  17. 返回 resultDesc。
注

Proxy 对象的 [[GetOwnProperty]] 强制执行以下不变量:

  • [[GetOwnProperty]] 的结果必须是 Property Descriptor 或 undefined。
  • 如果属性作为目标对象的不可配置自有属性存在,则不能报告该属性不存在。
  • 如果属性作为不可扩展目标对象的自有属性存在,则不能报告该属性不存在。
  • 如果属性不作为目标对象的自有属性存在并且目标对象不可扩展,则不能报告该属性存在。
  • 除非属性作为目标对象的不可配置自有属性存在,否则不能报告该属性不可配置。
  • 除非属性作为目标对象的不可配置且不可写自有属性存在,否则不能报告该属性同时不可配置且不可写。

10.5.6 [[DefineOwnProperty]] ( propertyKey, propertyDesc )

a Proxy exotic object obj的内部方法 [[DefineOwnProperty]],接收参数 propertyKey (属性键) 和 propertyDesc (属性描述符);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. 令 target 为 obj.[[ProxyTarget]]。
  3. 令 handler 为 obj.[[ProxyHandler]]。
  4. 断言:handler 是 Object。
  5. 令 trap 为 ? GetMethod(handler, "defineProperty")。
  6. 如果 trap 是 undefined,则
    1. 返回 ? target.[[DefineOwnProperty]](propertyKey, propertyDesc)。
  7. 令 propertyDescObj 为 FromPropertyDescriptor(propertyDesc)。
  8. 令 boolTrapResult 为 ToBoolean(? Call(trap, handler, « target, propertyKey, propertyDescObj »))。
  9. 如果 boolTrapResult 是 false,则返回 false。
  10. 令 targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)。
  11. 令 extensibleTarget 为 ? IsExtensible(target)。
  12. 如果 propertyDesc 具有 [[Configurable]] 字段且 propertyDesc.[[Configurable]] 是 false,则
    1. 令 settingConfigurableFalse 为 true。
  13. 否则,
    1. 令 settingConfigurableFalse 为 false。
  14. 如果 targetDesc 是 undefined,则
    1. 如果 extensibleTarget 是 false,则抛出 TypeError 异常。
    2. 如果 settingConfigurableFalse 是 true,则抛出 TypeError 异常。
  15. 否则,
    1. 如果 IsCompatiblePropertyDescriptor(extensibleTarget, propertyDesc, targetDesc) 是 false,则抛出 TypeError 异常。
    2. 如果 settingConfigurableFalse 是 true 且 targetDesc.[[Configurable]] 是 true,则抛出 TypeError 异常。
    3. 如果 IsDataDescriptor(targetDesc) 是 true、targetDesc.[[Configurable]] 是 false 且 targetDesc.[[Writable]] 是 true,则
      1. 如果 propertyDesc 具有 [[Writable]] 字段且 propertyDesc.[[Writable]] 是 false,则抛出 TypeError 异常。
  16. 返回 true。
注

Proxy 对象的 [[DefineOwnProperty]] 强制执行以下不变量:

  • [[DefineOwnProperty]] 的结果是 Boolean 值。
  • 如果目标对象不可扩展,则不能添加属性。
  • 除非目标对象存在对应的不可配置自有属性,否则属性不能是不可配置的。
  • 除非目标对象存在对应的不可配置且不可写自有属性,否则不可配置属性不能是不可写的。
  • 如果属性具有对应的目标对象属性,则使用 [[DefineOwnProperty]] 将该属性的 Property Descriptor 应用于目标对象时不会抛出异常。

10.5.7 [[HasProperty]] ( propertyKey )

a Proxy exotic object obj的内部方法 [[HasProperty]],接收参数 propertyKey (属性键);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. 令 target 为 obj.[[ProxyTarget]]。
  3. 令 handler 为 obj.[[ProxyHandler]]。
  4. 断言:handler 是 Object。
  5. 令 trap 为 ? GetMethod(handler, "has")。
  6. 如果 trap 是 undefined,则
    1. 返回 ? target.[[HasProperty]](propertyKey)。
  7. 令 boolTrapResult 为 ToBoolean(? Call(trap, handler, « target, propertyKey »))。
  8. 如果 boolTrapResult 是 false,则
    1. 令 targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)。
    2. 如果 targetDesc 不是 undefined,则
      1. 如果 targetDesc.[[Configurable]] 是 false,则抛出 TypeError 异常。
      2. 令 extensibleTarget 为 ? IsExtensible(target)。
      3. 如果 extensibleTarget 是 false,则抛出 TypeError 异常。
  9. 返回 boolTrapResult。
注

Proxy 对象的 [[HasProperty]] 强制执行以下不变量:

  • [[HasProperty]] 的结果是 Boolean 值。
  • 如果属性作为目标对象的不可配置自有属性存在,则不能报告该属性不存在。
  • 如果属性作为目标对象的自有属性存在且目标对象不可扩展,则不能报告该属性不存在。

10.5.8 [[Get]] ( propertyKey, receiver )

a Proxy exotic object obj的内部方法 [[Get]],接收参数 propertyKey (属性键) 和 receiver (ECMAScript 语言值);返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. 令 target 为 obj.[[ProxyTarget]]。
  3. 令 handler 为 obj.[[ProxyHandler]]。
  4. 断言:handler 是 Object。
  5. 令 trap 为 ? GetMethod(handler, "get")。
  6. 如果 trap 是 undefined,则
    1. 返回 ? target.[[Get]](propertyKey, receiver)。
  7. 令 trapResult 为 ? Call(trap, handler, « target, propertyKey, receiver »)。
  8. 令 targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)。
  9. 如果 targetDesc 不是 undefined 且 targetDesc.[[Configurable]] 是 false,则
    1. 如果 IsDataDescriptor(targetDesc) 是 true 且 targetDesc.[[Writable]] 是 false,则
      1. 如果 SameValue(trapResult, targetDesc.[[Value]]) 是 false,则抛出 TypeError 异常。
    2. 如果 IsAccessorDescriptor(targetDesc) 是 true 且 targetDesc.[[Getter]] 是 undefined,则
      1. 如果 trapResult 不是 undefined,则抛出 TypeError 异常。
  10. 返回 trapResult。
注

Proxy 对象的 [[Get]] 强制执行以下不变量:

  • 如果对应的目标对象属性是不可写、不可配置的自有数据属性,则为属性报告的值必须与对应目标对象属性的值相同。
  • 如果对应的目标对象属性是不可配置的自有访问器属性,并且其 [[Getter]] 特性为 undefined,则为该属性报告的值必须为 undefined。

10.5.9 [[Set]] ( propertyKey, value, receiver )

a Proxy exotic object obj的内部方法 [[Set]],接收参数 propertyKey (属性键)、value (ECMAScript 语言值) 和 receiver (ECMAScript 语言值);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. 令 target 为 obj.[[ProxyTarget]]。
  3. 令 handler 为 obj.[[ProxyHandler]]。
  4. 断言:handler 是 Object。
  5. 令 trap 为 ? GetMethod(handler, "set")。
  6. 如果 trap 是 undefined,则
    1. 返回 ? target.[[Set]](propertyKey, value, receiver)。
  7. 令 boolTrapResult 为 ToBoolean(? Call(trap, handler, « target, propertyKey, value, receiver »))。
  8. 如果 boolTrapResult 是 false,则返回 false。
  9. 令 targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)。
  10. 如果 targetDesc 不是 undefined 且 targetDesc.[[Configurable]] 是 false,则
    1. 如果 IsDataDescriptor(targetDesc) 是 true 且 targetDesc.[[Writable]] 是 false,则
      1. 如果 SameValue(value, targetDesc.[[Value]]) 是 false,则抛出 TypeError 异常。
    2. 如果 IsAccessorDescriptor(targetDesc) 是 true,则
      1. 如果 targetDesc.[[Setter]] 是 undefined,则抛出 TypeError 异常。
  11. 返回 true。
注

Proxy 对象的 [[Set]] 强制执行以下不变量:

  • [[Set]] 的结果是 Boolean 值。
  • 如果对应目标对象属性是不可写、不可配置的自有数据属性,则不能将属性值更改为与对应目标对象属性值不同的值。
  • 如果对应目标对象属性是不可配置的自有访问器属性,并且其 [[Setter]] 特性为 undefined,则不能设置该属性的值。

10.5.10 [[Delete]] ( propertyKey )

a Proxy exotic object obj的内部方法 [[Delete]],接收参数 propertyKey (属性键);返回值:(正常完成 (值:Boolean) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. 令 target 为 obj.[[ProxyTarget]]。
  3. 令 handler 为 obj.[[ProxyHandler]]。
  4. 断言:handler 是 Object。
  5. 令 trap 为 ? GetMethod(handler, "deleteProperty")。
  6. 如果 trap 是 undefined,则
    1. 返回 ? target.[[Delete]](propertyKey)。
  7. 令 boolTrapResult 为 ToBoolean(? Call(trap, handler, « target, propertyKey »))。
  8. 如果 boolTrapResult 是 false,则返回 false。
  9. 令 targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)。
  10. 如果 targetDesc 是 undefined,则返回 true。
  11. 如果 targetDesc.[[Configurable]] 是 false,则抛出 TypeError 异常。
  12. 令 extensibleTarget 为 ? IsExtensible(target)。
  13. 如果 extensibleTarget 是 false,则抛出 TypeError 异常。
  14. 返回 true。
注

Proxy 对象的 [[Delete]] 强制执行以下不变量:

  • [[Delete]] 的结果是 Boolean 值。
  • 如果属性作为目标对象的不可配置自有属性存在,则不能报告该属性已删除。
  • 如果属性作为目标对象的自有属性存在且目标对象不可扩展,则不能报告该属性已删除。

10.5.11 [[OwnPropertyKeys]] ( )

a Proxy exotic object obj的内部方法 [[OwnPropertyKeys]],接收无参数;返回值:(正常完成 (值:列表 (元素:属性键)) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. 令 target 为 obj.[[ProxyTarget]]。
  3. 令 handler 为 obj.[[ProxyHandler]]。
  4. 断言:handler 是 Object。
  5. 令 trap 为 ? GetMethod(handler, "ownKeys")。
  6. 如果 trap 是 undefined,则
    1. 返回 ? target.[[OwnPropertyKeys]]()。
  7. 令 trapResultArray 为 ? Call(trap, handler, « target »)。
  8. 令 trapResult 为 ? CreateListFromArrayLike(trapResultArray, property-key)。
  9. 如果 trapResult 包含任何重复条目,则抛出 TypeError 异常。
  10. 令 extensibleTarget 为 ? IsExtensible(target)。
  11. 令 targetKeys 为 ? target.[[OwnPropertyKeys]]()。
  12. 断言:targetKeys 是属性键的 List。
  13. 断言:targetKeys 不包含重复条目。
  14. 令 targetConfigurableKeys 为新的空 List。
  15. 令 targetNonconfigurableKeys 为新的空 List。
  16. 对 targetKeys 的每个元素 key,执行
    1. 令 propertyDesc 为 ? target.[[GetOwnProperty]](key)。
    2. 如果 propertyDesc 不是 undefined 且 propertyDesc.[[Configurable]] 是 false,则
      1. 将 key 追加到 targetNonconfigurableKeys。
    3. 否则,
      1. 将 key 追加到 targetConfigurableKeys。
  17. 如果 extensibleTarget 是 true 且 targetNonconfigurableKeys 为空,则
    1. 返回 trapResult。
  18. 令 uncheckedResultKeys 为一个 List,其元素是 trapResult 的元素。
  19. 对 targetNonconfigurableKeys 的每个元素 key,执行
    1. 如果 uncheckedResultKeys 不包含 key,则抛出 TypeError 异常。
    2. 从 uncheckedResultKeys 中移除 key。
  20. 如果 extensibleTarget 是 true,则返回 trapResult。
  21. 对 targetConfigurableKeys 的每个元素 key,执行
    1. 如果 uncheckedResultKeys 不包含 key,则抛出 TypeError 异常。
    2. 从 uncheckedResultKeys 中移除 key。
  22. 如果 uncheckedResultKeys 不为空,则抛出 TypeError 异常。
  23. 返回 trapResult。
注

Proxy 对象的 [[OwnPropertyKeys]] 强制执行以下不变量:

  • [[OwnPropertyKeys]] 的结果是 List。
  • 返回的 List 不包含重复条目。
  • 返回的 List 的每个元素都是属性键。
  • 结果 List 必须包含目标对象所有不可配置自有属性的键。
  • 如果目标对象不可扩展,则结果 List 必须包含目标对象所有自有属性的键,且不得包含其他值。

10.5.12 [[Call]] ( thisArg, argList )

a Proxy exotic object obj的内部方法 [[Call]],接收参数 thisArg (ECMAScript 语言值) 和 argList (列表 (元素:ECMAScript 语言值));返回值:(正常完成 (值:ECMAScript 语言值) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. 令 target 为 obj.[[ProxyTarget]]。
  3. 令 handler 为 obj.[[ProxyHandler]]。
  4. 断言:handler 是 Object。
  5. 令 trap 为 ? GetMethod(handler, "apply")。
  6. 如果 trap 是 undefined,则
    1. 返回 ? Call(target, thisArg, argList)。
  7. 令 argArray 为 CreateArrayFromList(argList)。
  8. 返回 ? Call(trap, handler, « target, thisArg, argArray »)。
注

只有当 Proxy 异质对象的 [[ProxyTarget]] 内部槽初始值是具有 [[Call]] 内部方法的对象时,该 Proxy 异质对象才具有 [[Call]] 内部方法。

10.5.13 [[Construct]] ( argList, newTarget )

a Proxy exotic object obj的内部方法 [[Construct]],接收参数 argList (列表 (元素:ECMAScript 语言值)) 和 newTarget (构造函数);返回值:(正常完成 (值:Object) 或 抛出完成)。 调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. 令 target 为 obj.[[ProxyTarget]]。
  3. 断言:IsConstructor(target) 是 true。
  4. 令 handler 为 obj.[[ProxyHandler]]。
  5. 断言:handler 是 Object。
  6. 令 trap 为 ? GetMethod(handler, "construct")。
  7. 如果 trap 是 undefined,则
    1. 返回 ? Construct(target, argList, newTarget)。
  8. 令 argArray 为 CreateArrayFromList(argList)。
  9. 令 newObj 为 ? Call(trap, handler, « target, argArray, newTarget »)。
  10. 如果 newObj 不是 Object,则抛出 TypeError 异常。
  11. 返回 newObj。
注 1

只有当 Proxy 异质对象的 [[ProxyTarget]] 内部槽初始值是具有 [[Construct]] 内部方法的对象时,该 Proxy 异质对象才具有 [[Construct]] 内部方法。

注 2

Proxy 对象的 [[Construct]] 强制执行以下不变量:

  • [[Construct]] 的结果必须是 Object。

10.5.14 ValidateNonRevokedProxy ( proxy )

抽象操作 ValidateNonRevokedProxy,接收参数 proxy (Proxy 特异对象);返回值:(正常完成 (值:unused) 或 抛出完成)。 如果 proxy 已被撤销,则它会抛出 TypeError 异常。 调用时执行以下步骤:

  1. 如果 proxy.[[ProxyTarget]] 是 null,则抛出 TypeError 异常。
  2. 断言:proxy.[[ProxyHandler]] 不是 null。
  3. 返回 unused。

10.5.15 ProxyCreate ( target, handler )

抽象操作 ProxyCreate,接收参数 target (ECMAScript 语言值) 和 handler (ECMAScript 语言值);返回值:(正常完成 (值:Proxy 特异对象) 或 抛出完成)。 它用于规定创建新的 Proxy 对象。 调用时执行以下步骤:

  1. 如果 target 不是 Object,则抛出 TypeError 异常。
  2. 如果 handler 不是 Object,则抛出 TypeError 异常。
  3. 令 proxy 为 MakeBasicObject(« [[ProxyHandler]], [[ProxyTarget]] »)。
  4. 将 proxy 的基本内部方法([[Call]] 和 [[Construct]] 除外)设置为 10.5 中规定的定义。
  5. 如果 IsCallable(target) 是 true,则
    1. 按 10.5.12 中的规定设置 proxy.[[Call]]。
    2. 如果 IsConstructor(target) 是 true,则
      1. 按 10.5.13 中的规定设置 proxy.[[Construct]]。
  6. 将 proxy.[[ProxyTarget]] 设置为 target。
  7. 将 proxy.[[ProxyHandler]] 设置为 handler。
  8. 返回 proxy。