10 普通对象与异质对象行为

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

所有普通对象都有一个名为 [[Prototype]] 的内部槽。该内部槽的值要么是 null, 要么是一个对象,并用于实现继承。假设一个名为 propertyKey 的属性在普通对象 obj 上不存在,但存在于其 [[Prototype]] 对象上。如果 propertyKey 指的是 [[Prototype]] 对象上的一个数据属性,那么 obj 在获取访问时会继承它,从而表 现得如同 propertyKeyobj 的一个属性一样。如果 propertyKey 指的是 [[Prototype]] 对象上的一个可写数据属性,那么在 obj 上对 propertyKey 的设 值访问会在 obj 上创建一个名为 propertyKey 的新数据属性。如果 propertyKey 指的是 [[Prototype]] 对象上的一个不可写数据属性,那么在 obj 上对 propertyKey 的设置访问会失败。如果 propertyKey 指的是 [[Prototype]] 对象上的一个访问器属 性,那么该访问器会被 obj 同时继承用于获取访问和设置访问。

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

在下面的算法描述中,假设 obj 是一个普通对象propertyKey 是一个属性键值, value 是任意 ECMAScript 语言值,而 desc 是一个属性描述符记录。

每个普通对象内部方法都委托给一个名称相近的抽象操作。如果这样的抽象操作依赖于 另一个内部方法,那么该内部方法会在 obj 上被调用,而不是直接调用那个名称相近 的抽象操作。这些语义确保了当普通对象内部方法应用于异质对象时,会调用它们被覆写 的内部方法。

10.1.1 [[GetPrototypeOf]] ( )

The [[GetPrototypeOf]] internal method of 一个普通对象 obj takes no arguments and returns 一个正常完成,包含一个 Object 或 null. It performs the following steps when called:

  1. 返回 OrdinaryGetPrototypeOf(obj)。

10.1.1.1 OrdinaryGetPrototypeOf ( obj )

The abstract operation OrdinaryGetPrototypeOf takes argument obj (一个 Object) and returns 一个 Object 或 null. It performs the following steps when called:

  1. 返回 obj.[[Prototype]]

10.1.2 [[SetPrototypeOf]] ( proto )

The [[SetPrototypeOf]] internal method of 一个普通对象 obj takes argument proto (一个 Object 或 null) and returns 一个正常完成,包含一个 Boolean. It performs the following steps when called:

  1. 返回 OrdinarySetPrototypeOf(obj, proto)。

10.1.2.1 OrdinarySetPrototypeOf ( obj, proto )

The abstract operation OrdinarySetPrototypeOf takes arguments obj (一个 Object) and proto (一个 Object 或 null) and returns 一个 Boolean. It performs the following steps when called:

  1. currentobj.[[Prototype]]
  2. 如果 SameValue(proto, current) 为 true,返回 true
  3. extensibleobj.[[Extensible]]
  4. 如果 extensiblefalse,返回 false
  5. cursorproto
  6. donefalse
  7. 重复,当 donefalse 时,
    1. 如果 cursornull,那么
      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
Note

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

10.1.3 [[IsExtensible]] ( )

The [[IsExtensible]] internal method of 一个普通对象 obj takes no arguments and returns 一个正常完成,包含一个 Boolean. It performs the following steps when called:

  1. 返回 OrdinaryIsExtensible(obj)。

10.1.3.1 OrdinaryIsExtensible ( obj )

The abstract operation OrdinaryIsExtensible takes argument obj (一个 Object) and returns 一个 Boolean. It performs the following steps when called:

  1. 返回 obj.[[Extensible]]

10.1.4 [[PreventExtensions]] ( )

The [[PreventExtensions]] internal method of 一个普通对象 obj takes no arguments and returns 一个正常完成,包含 true. It performs the following steps when called:

  1. 返回 OrdinaryPreventExtensions(obj)。

10.1.4.1 OrdinaryPreventExtensions ( obj )

The abstract operation OrdinaryPreventExtensions takes argument obj (一个 Object) and returns true. It performs the following steps when called:

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

10.1.5 [[GetOwnProperty]] ( propertyKey )

The [[GetOwnProperty]] internal method of 一个普通对象 obj takes argument propertyKey (一个属性键) and returns 一个正常完成,包含一个属性描述符或 undefined. It performs the following steps when called:

  1. 返回 OrdinaryGetOwnProperty(obj, propertyKey)。

10.1.5.1 OrdinaryGetOwnProperty ( obj, propertyKey )

The abstract operation OrdinaryGetOwnProperty takes arguments obj (一个 Object) and propertyKey (一个属性键) and returns 一个属性描述符或 undefined. It performs the following steps when called:

  1. 如果 obj 没有一个键为 propertyKey 的自有属性,返回 undefined
  2. desc 为一个新创建的、不含任何字段的属性描述符。
  3. ownPropertyobj 的键为 propertyKey 的自有属性。
  4. 如果 ownProperty 是一个数据属性,那么
    1. desc.[[Value]] 设为 ownProperty[[Value]] 特性的值。
    2. desc.[[Writable]] 设为 ownProperty[[Writable]] 特性的值。
  5. 否则,
    1. 断言:ownProperty 是一个访问器属性
    2. desc.[[Get]] 设为 ownProperty[[Get]] 特性的值。
    3. desc.[[Set]] 设为 ownProperty[[Set]] 特性的值。
  6. desc.[[Enumerable]] 设为 ownProperty[[Enumerable]] 特性的值。
  7. desc.[[Configurable]] 设为 ownProperty[[Configurable]] 特性的值。
  8. 返回 desc

10.1.6 [[DefineOwnProperty]] ( propertyKey, desc )

The [[DefineOwnProperty]] internal method of 一个普通对象 obj takes arguments propertyKey (一个属性键) and desc (一个属性描述符) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

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

10.1.6.1 OrdinaryDefineOwnProperty ( obj, propertyKey, desc )

The abstract operation OrdinaryDefineOwnProperty takes arguments obj (一个 Object), propertyKey (一个属性键), and desc (一个属性描述符) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

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

10.1.6.2 IsCompatiblePropertyDescriptor ( extensible, desc, current )

The abstract operation IsCompatiblePropertyDescriptor takes arguments extensible (一个 Boolean), desc (一个属性描述符), and current (一个属性描述符或 undefined) and returns 一个 Boolean. It performs the following steps when called:

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

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

The abstract operation ValidateAndApplyPropertyDescriptor takes arguments obj (一个 Object 或 undefined), propertyKey (一个属性键), extensible (一个 Boolean), desc (一个属性描述符), and current (一个属性描述符或 undefined) and returns 一个 Boolean. 当且仅当 desc 能够在维持 不变量 的前提下,被应用为一个具有指定 extensibility 和当前属性 current 的对象的 属性时,它返回 true。当这种应用是可能的且 obj 不是 undefined 时,它会 对名为 propertyKey 的属性执行该应用(必要时会创建该属性)。 It performs the following steps when called:

  1. 断言:propertyKey 是一个属性键
  2. 如果 currentundefined,那么
    1. 如果 extensiblefalse,返回 false
    2. 如果 objundefined,返回 true
    3. 如果 IsAccessorDescriptor(desc) 为 true,那么
      1. 在对象 obj 上创建一个名为 propertyKey 的自有访问器属性,其 [[Get]][[Set]][[Enumerable]][[Configurable]] 特性如果 desc 具有对应字段,则设为对应字段的值,否则设为该特性的 默认值
    4. 否则,
      1. 在对象 obj 上创建一个名为 propertyKey 的自有数据属性,其 [[Value]][[Writable]][[Enumerable]][[Configurable]] 特性如果 desc 具有对应字段,则设为对应字段的值,否则设为该特性的 默认值
    5. 返回 true
  3. 断言:current 是一个完全填充的属性描述符。
  4. 如果 desc 没有任何字段,返回 true
  5. 如果 current.[[Configurable]]false,那么
    1. 如果 desc[[Configurable]] 字段且 desc.[[Configurable]]true,返回 false
    2. 如果 desc[[Enumerable]] 字段且 desc.[[Enumerable]] 不等于 current.[[Enumerable]],返回 false
    3. 如果 IsGenericDescriptor(desc) 为 falseIsAccessorDescriptor(desc) 不等于 IsAccessorDescriptor(current),返回 false
    4. 如果 IsAccessorDescriptor(current) 为 true,那么
      1. 如果 desc[[Get]] 字段且 SameValue(desc.[[Get]], current.[[Get]]) 为 false,返回 false
      2. 如果 desc[[Set]] 字段且 SameValue(desc.[[Set]], current.[[Set]]) 为 false,返回 false
    5. 否则如果 current.[[Writable]]false,那么
      1. 如果 desc[[Writable]] 字段且 desc.[[Writable]]true,返回 false
      2. NOTE: SameValueNaN 值返回 true,而该值可能可以通过其他方式区分。 在这里返回可确保 obj 的任何现有属性保持未被修改。
      3. 如果 desc[[Value]] 字段,返回 SameValue(desc.[[Value]], current.[[Value]])。
  6. 如果 obj 不是 undefined,那么
    1. 如果 IsDataDescriptor(current) 为 trueIsAccessorDescriptor(desc) 为 true,那么
      1. 如果 desc[[Configurable]] 字段,令 configurabledesc.[[Configurable]];否则令 configurablecurrent.[[Configurable]]
      2. 如果 desc[[Enumerable]] 字段,令 enumerabledesc.[[Enumerable]];否则令 enumerablecurrent.[[Enumerable]]
      3. 用一个访问器属性替换对象 obj 中名为 propertyKey 的属性,该访问器属性[[Configurable]][[Enumerable]] 特性分别设为 configurableenumerable,而其 [[Get]][[Set]] 特性如果 desc 具有对应字段,则设为对应字段的值,否则设为该特性的 默认值
    2. 否则如果 IsAccessorDescriptor(current) 为 trueIsDataDescriptor(desc) 为 true,那么
      1. 如果 desc[[Configurable]] 字段,令 configurabledesc.[[Configurable]];否则令 configurablecurrent.[[Configurable]]
      2. 如果 desc[[Enumerable]] 字段,令 enumerabledesc.[[Enumerable]];否则令 enumerablecurrent.[[Enumerable]]
      3. 用一个数据属性替换对象 obj 中名为 propertyKey 的属性,该数据属性[[Configurable]][[Enumerable]] 特性分别设为 configurableenumerable,而其 [[Value]][[Writable]] 特性如果 desc 具有对应字段,则设为对应字段的值,否则设为该特性的 默认值
    3. 否则,
      1. 对于 desc 的每个字段名 fieldName,将对象 obj 中名为 propertyKey 的属性上名为 fieldName 的特性设为 descfieldName 字段的值。
  7. 返回 true

10.1.7 [[HasProperty]] ( propertyKey )

The [[HasProperty]] internal method of 一个普通对象 obj takes argument propertyKey (一个属性键) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

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

10.1.7.1 OrdinaryHasProperty ( obj, propertyKey )

The abstract operation OrdinaryHasProperty takes arguments obj (一个 Object) and propertyKey (一个属性键) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  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 )

The [[Get]] internal method of 一个普通对象 obj takes arguments propertyKey (一个属性键) and receiver (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个抛出完成. It performs the following steps when called:

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

10.1.8.1 OrdinaryGet ( obj, propertyKey, receiver )

The abstract operation OrdinaryGet takes arguments obj (一个 Object), propertyKey (一个属性键), and receiver (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个抛出完成. It performs the following steps when called:

  1. desc 为 ? obj.[[GetOwnProperty]](propertyKey)
  2. 如果 descundefined,那么
    1. parent 为 ? obj.[[GetPrototypeOf]]()
    2. 如果 parentnull,返回 undefined
    3. 返回 ? parent.[[Get]](propertyKey, receiver)
  3. 如果 IsDataDescriptor(desc) 为 true,返回 desc.[[Value]]
  4. 断言:IsAccessorDescriptor(desc) 为 true
  5. getterdesc.[[Get]]
  6. 如果 getterundefined,返回 undefined
  7. 返回 ? Call(getter, receiver)。

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

The [[Set]] internal method of 一个普通对象 obj takes arguments propertyKey (一个属性键), value (一个 ECMAScript 语言值), and receiver (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

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

10.1.9.1 OrdinarySet ( obj, propertyKey, value, receiver )

The abstract operation OrdinarySet takes arguments obj (一个 Object), propertyKey (一个属性键), value (一个 ECMAScript 语言值), and receiver (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

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

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

The abstract operation OrdinarySetWithOwnDescriptor takes arguments obj (一个 Object), propertyKey (一个属性键), value (一个 ECMAScript 语言值), receiver (一个 ECMAScript 语言值), and ownDesc (一个属性描述符或 undefined) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 ownDescundefined,那么
    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. existingDescriptor 为 ? receiver.[[GetOwnProperty]](propertyKey)
    4. 如果 existingDescriptorundefined,那么
      1. 断言:receiver 当前并不具有属性 propertyKey
      2. 返回 ? CreateDataProperty(receiver, propertyKey, value)。
    5. 如果 IsAccessorDescriptor(existingDescriptor) 为 true,返回 false
    6. 如果 existingDescriptor.[[Writable]]false,返回 false
    7. valueDesc 为属性描述符 PropertyDescriptor { [[Value]]: value }。
    8. 返回 ? receiver.[[DefineOwnProperty]](propertyKey, valueDesc)
  3. 断言:IsAccessorDescriptor(ownDesc) 为 true
  4. setterownDesc.[[Set]]
  5. 如果 setterundefined,返回 false
  6. 执行 ? Call(setter, receiver, « value »)。
  7. 返回 true

10.1.10 [[Delete]] ( propertyKey )

The [[Delete]] internal method of 一个普通对象 obj takes argument propertyKey (一个属性键) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

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

10.1.10.1 OrdinaryDelete ( obj, propertyKey )

The abstract operation OrdinaryDelete takes arguments obj (一个 Object) and propertyKey (一个属性键) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. desc 为 ? obj.[[GetOwnProperty]](propertyKey)
  2. 如果 descundefined,返回 true
  3. 如果 desc.[[Configurable]]true,那么
    1. obj 中移除名称为 propertyKey 的自有属性。
    2. 返回 true
  4. 返回 false

10.1.11 [[OwnPropertyKeys]] ( )

The [[OwnPropertyKeys]] internal method of 一个普通对象 obj takes no arguments and returns 一个正常完成,包含一个属性键列表. It performs the following steps when called:

  1. 返回 OrdinaryOwnPropertyKeys(obj)。

10.1.11.1 OrdinaryOwnPropertyKeys ( obj )

The abstract operation OrdinaryOwnPropertyKeys takes argument obj (一个 Object) and returns 一个属性键列表. It performs the following steps when called:

  1. keys 为一个新的空列表。
  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 ] )

The abstract operation OrdinaryObjectCreate takes argument proto (一个 Object 或 null) and optional argument additionalInternalSlotsList (一个内部槽名称列表) and returns 一个 Object. 它用于规定新普通对象的运行时创建。additionalInternalSlotsList 包含除了 [[Prototype]][[Extensible]] 之外,必须作为对象一部分定义的额外内部槽 名称。如果未提供 additionalInternalSlotsList,则使用一个新的空列表。 It performs the following steps when called:

  1. internalSlotsList 为 « [[Prototype]], [[Extensible]] »。
  2. 如果 additionalInternalSlotsList 存在,则将 internalSlotsList 设为 internalSlotsListadditionalInternalSlotsList 的列表串接。
  3. objMakeBasicObject(internalSlotsList)。
  4. obj.[[Prototype]] 设为 proto
  5. 返回 obj
Note

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

10.1.13 OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] )

The abstract operation OrdinaryCreateFromConstructor takes arguments constructor (一个函数对象) and intrinsicDefaultProto (一个 String) and optional argument internalSlotsList (一个内部槽名称列表) and returns 要么是一个正常完成,包含一个 Object,要么是一个抛出完成. 它创建一个普通对象,其 [[Prototype]] 值会从构造函数的 "prototype" 属 性中获取(如果它存在)。否则,使用由 intrinsicDefaultProto 命名的内在对象 作为 [[Prototype]]internalSlotsList 包含必须作为对象一部分定义的额外内 部槽名称。如果未提供 internalSlotsList,则使用一个新的空列表。 It performs the following steps when called:

  1. 断言:intrinsicDefaultProto 是本规范中某个内在对象的名称。相应的对象必须是一个意图用作对象 [[Prototype]] 值的内在对象。
  2. proto 为 ? GetPrototypeFromConstructor(constructor, intrinsicDefaultProto)。
  3. 如果 internalSlotsList 存在,令 slotsListinternalSlotsList
  4. 否则,令 slotsList 为一个新的空列表。
  5. 返回 OrdinaryObjectCreate(proto, slotsList)。

10.1.14 GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto )

The abstract operation GetPrototypeFromConstructor takes arguments constructor (一个函数对象) and intrinsicDefaultProto (一个 String) and returns 要么是一个正常完成,包含一个 Object,要么是一个抛出完成. 它决定在创建与某个特定构造函数相对应的对象时应使用的 [[Prototype]] 值。 这个值会从构造函数的 "prototype" 属性中获取(如果它存在)。否则,使用由 intrinsicDefaultProto 命名的内在对象作为 [[Prototype]]。 It performs the following steps when called:

  1. 断言:intrinsicDefaultProto 是本规范中某个内在对象的名称。相应的对象必须是一个意图用作对象 [[Prototype]] 值的内在对象。
  2. proto 为 ? Get(constructor, "prototype")。
  3. 如果 proto 不是一个 Object,那么
    1. realm 为 ? GetFunctionRealm(constructor)。
    2. proto 设为 realm 中名为 intrinsicDefaultProto 的内在对象。
  4. 返回 proto
Note

如果 constructor 没有提供 [[Prototype]] 值,则所使用的默认值取自 constructor 函数所属的 realm,而不是取自当前运行的执行上下文

10.1.15 RequireInternalSlot ( obj, internalSlot )

The abstract operation RequireInternalSlot takes arguments obj (一个 ECMAScript 语言值) and internalSlot (一个内部槽名称) and returns 要么是一个正常完成,包含 unused,要么是一个抛出完成. 除非 obj 是一个 Object 且具有给定的内部槽,否则它会抛出一个异常。 It performs the following steps when called:

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

10.2 ECMAScript 函数对象

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

除了 [[Extensible]][[Prototype]] 之外,ECMAScript 函数对象还具有列于 Table 25 中的内部槽。

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

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

10.2.1 [[Call]] ( thisArgument, argumentsList )

The [[Call]] internal method of 一个 ECMAScript 函数对象 func takes arguments thisArgument (一个 ECMAScript 语言值) and argumentsList (一个 ECMAScript 语言值列表) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个抛出完成. It performs the following steps when called:

  1. callerContext 为当前运行的执行上下文
  2. calleeContextPrepareForOrdinaryCall(func, undefined)。
  3. 断言:calleeContext 现在是当前运行的执行上下文
  4. 如果 func.[[IsClassConstructor]]true,那么
    1. error 为一个新创建的 TypeError 对象。
    2. NOTE: errorcalleeContext 中创建,并与 func 关联的 Realm Record 相关联。
    3. 执行上下文栈中移除 calleeContext,并恢复 callerContext 为当前 运行的执行上下文
    4. 抛出 error
  5. 执行 OrdinaryCallBindThis(func, calleeContext, thisArgument)。
  6. resultCompletion(OrdinaryCallEvaluateBody(func, argumentsList))。
  7. 执行上下文栈中移除 calleeContext, 并恢复 callerContext 为当前运行的执行上下文
  8. 如果 result 是一个返回完成,返回 result.[[Value]]
  9. 断言:result 是一个抛出完成。
  10. 返回 ? result
Note

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

10.2.1.1 PrepareForOrdinaryCall ( func, newTarget )

The abstract operation PrepareForOrdinaryCall takes arguments func (一个 ECMAScript 函数对象) and newTarget (一个 Object 或 undefined) and returns 一个执行上下文. It performs the following steps when called:

  1. callerContext 为当前运行的执行上下文
  2. calleeContext 为一个新的 ECMAScript 代码执行上下文
  3. calleeContext 的 Function 设为 func
  4. calleeRealmfunc.[[Realm]]
  5. calleeContextRealm 设为 calleeRealm
  6. calleeContext 的 ScriptOrModule 设为 func.[[ScriptOrModule]]
  7. localEnvNewFunctionEnvironment(func, newTarget)。
  8. calleeContext 的 LexicalEnvironment 设为 localEnv
  9. calleeContext 的 VariableEnvironment 设为 localEnv
  10. calleeContext 的 PrivateEnvironment 设为 func.[[PrivateEnvironment]]
  11. 如果 callerContext 尚未挂起,则挂起 callerContext
  12. calleeContext 压入执行上下文栈calleeContext 现在是当前运行的 执行上下文
  13. NOTE: 从此之后产生的任何异常对象都与 calleeRealm 相关联。
  14. 返回 calleeContext

10.2.1.2 OrdinaryCallBindThis ( func, calleeContext, thisArgument )

The abstract operation OrdinaryCallBindThis takes arguments func (一个 ECMAScript 函数对象), calleeContext (一个执行上下文), and thisArgument (一个 ECMAScript 语言值) and returns unused. It performs the following steps when called:

  1. thisModefunc.[[ThisMode]]
  2. 如果 thisModelexical,返回 unused
  3. calleeRealmfunc.[[Realm]]
  4. localEnvcalleeContext 的 LexicalEnvironment。
  5. 如果 thisModestrict,那么
    1. thisValuethisArgument
  6. 否则,
    1. 如果 thisArgumentundefinednull,那么
      1. globalEnvcalleeRealm.[[GlobalEnv]]
      2. 断言:globalEnv 是一个 Global Environment Record
      3. thisValueglobalEnv.[[GlobalThisValue]]
    2. 否则,
      1. thisValue 为 ! ToObject(thisArgument)。
      2. NOTE: ToObject 使用 calleeRealm 产生包装对象。
  7. 断言:localEnv 是一个 Function Environment Record
  8. 断言:下一步绝不会返回一个突然完成,因为 localEnv.[[ThisBindingStatus]] 不是 initialized
  9. 执行 ! BindThisValue(localEnv, thisValue)。
  10. 返回 unused

10.2.1.3 Runtime Semantics: EvaluateBody

The syntax-directed operation EvaluateBody takes arguments func (一个 ECMAScript 函数对象) and argumentsList (一个 ECMAScript 语言值列表) and returns 一个返回完成或一个抛出完成. It is defined piecewise over the following productions:

FunctionBody : FunctionStatementList
  1. 返回 ? 对 FunctionBody 执行 EvaluateFunctionBody,并以 funcargumentsList 为参数。
ConciseBody : ExpressionBody
  1. 返回 ? 对 ConciseBody 执行 EvaluateConciseBody,并以 funcargumentsList 为参数。
GeneratorBody : FunctionBody
  1. 返回 ? 对 GeneratorBody 执行 EvaluateGeneratorBody,并以 funcargumentsList 为参数。
AsyncGeneratorBody : FunctionBody
  1. 返回 ? 对 AsyncGeneratorBody 执行 EvaluateAsyncGeneratorBody,并以 funcargumentsList 为参数。
AsyncFunctionBody : FunctionBody
  1. 返回 ? 对 AsyncFunctionBody 执行 EvaluateAsyncFunctionBody,并以 funcargumentsList 为参数。
AsyncConciseBody : ExpressionBody
  1. 返回 ? 对 AsyncConciseBody 执行 EvaluateAsyncConciseBody,并以 funcargumentsList 为参数。
Initializer : = AssignmentExpression
  1. 断言:argumentsList 为空。
  2. 断言:func.[[ClassFieldInitializerName]] 不为 empty
  3. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 为 true,那么
    1. value 为 ? 对 Initializer 执行 NamedEvaluation,并以 func.[[ClassFieldInitializerName]] 为参数。
  4. 否则,
    1. rhs 为 ? 对 AssignmentExpression 求值。
    2. value 为 ? GetValue(rhs)。
  5. 返回 ReturnCompletion(value)。
Note

尽管字段初始化器构成了一个函数边界,调用 FunctionDeclarationInstantiation 不会产生任何可观察效果,因此被省略。

ClassStaticBlockBody : ClassStaticBlockStatementList
  1. 断言:argumentsList 为空。
  2. 返回 ? 对 ClassStaticBlockBody 执行 EvaluateClassStaticBlockBody, 并以 func 为参数。

10.2.1.4 OrdinaryCallEvaluateBody ( func, argumentsList )

The abstract operation OrdinaryCallEvaluateBody takes arguments func (一个 ECMAScript 函数对象) and argumentsList (一个 ECMAScript 语言值列表) and returns 一个返回完成或一个抛出完成. It performs the following steps when called:

  1. 返回 ? 对 func.[[ECMAScriptCode]] 执行 EvaluateBody,并以 funcargumentsList 为参数。

10.2.2 [[Construct]] ( argumentsList, newTarget )

The [[Construct]] internal method of 一个 ECMAScript 函数对象 func takes arguments argumentsList (一个 ECMAScript 语言值列表) and newTarget (一个构造器) and returns 要么是一个正常完成,包含一个 Object,要么是一个抛出完成. It performs the following steps when called:

  1. callerContext 为当前运行的执行上下文
  2. kindfunc.[[ConstructorKind]]
  3. 如果 kindbase,那么
    1. thisArgument 为 ? OrdinaryCreateFromConstructor(newTarget, "%Object.prototype%")。
  4. calleeContextPrepareForOrdinaryCall(func, newTarget)。
  5. 断言:calleeContext 现在是当前运行的执行上下文
  6. 如果 kindbase,那么
    1. 执行 OrdinaryCallBindThis(func, calleeContext, thisArgument)。
    2. initializeResultCompletion(InitializeInstanceElements(thisArgument, func))。
    3. 如果 initializeResult 是一个突然完成,那么
      1. 执行上下文栈中移除 calleeContext,并恢复 callerContext 为当前运行的执行上下文
      2. 返回 ? initializeResult
  7. constructorEnvcalleeContext 的 LexicalEnvironment。
  8. resultCompletion(OrdinaryCallEvaluateBody(func, argumentsList))。
  9. 执行上下文栈中移除 calleeContext,并恢复 callerContext 为当前运行的执行上下文
  10. 如果 result 是一个抛出完成,那么
    1. 返回 ? result
  11. 断言:result 是一个返回完成。
  12. 如果 result.[[Value]] 是一个 Object,返回 result.[[Value]]
  13. 如果 kindbase,返回 thisArgument
  14. 如果 result.[[Value]] 不是 undefined,抛出一个 TypeError 异常。
  15. thisBinding 为 ? constructorEnv.GetThisBinding()。
  16. 断言:thisBinding 是一个 Object。
  17. 返回 thisBinding

10.2.3 OrdinaryFunctionCreate ( functionPrototype, sourceText, parameterList, body, thisMode, env, privateEnv )

The abstract operation OrdinaryFunctionCreate takes arguments functionPrototype (一个 Object), sourceText (一个 Unicode 码点序列), parameterList (一个 Parse Node), body (一个 Parse Node), thisMode (lexical-thisnon-lexical-this), env (一个 Environment Record), and privateEnv (一个 PrivateEnvironment Recordnull) and returns 一个 ECMAScript 函数对象. 它用于规定在运行时创建一个新函数,该函数具有默认的 [[Call]] 内部方法且没 有 [[Construct]] 内部方法(尽管之后可以通过 MakeConstructor 之类的操作添 加)。sourceText 是所创建函数的语法定义的源文本。 It performs the following steps when called:

  1. internalSlotsListTable 25 中列出的内部槽。
  2. funcOrdinaryObjectCreate(functionPrototype, internalSlotsList)。
  3. func.[[Call]] 设为 10.2.1 中规定的定义。
  4. func.[[SourceText]] 设为 sourceText
  5. func.[[FormalParameters]] 设为 parameterList
  6. func.[[ECMAScriptCode]] 设为 body
  7. strictIsStrict(body)。
  8. func.[[Strict]] 设为 strict
  9. 如果 thisModelexical-this,将 func.[[ThisMode]] 设为 lexical
  10. 否则如果 stricttrue,将 func.[[ThisMode]] 设为 strict
  11. 否则,将 func.[[ThisMode]] 设为 global
  12. func.[[IsClassConstructor]] 设为 false
  13. func.[[Environment]] 设为 env
  14. func.[[PrivateEnvironment]] 设为 privateEnv
  15. func.[[ScriptOrModule]] 设为 GetActiveScriptOrModule()。
  16. func.[[Realm]] 设为当前 Realm Record
  17. func.[[HomeObject]] 设为 undefined
  18. func.[[Fields]] 设为一个新的空列表。
  19. func.[[PrivateMethods]] 设为一个新的空列表。
  20. func.[[ClassFieldInitializerName]] 设为 empty
  21. lenparameterListExpectedArgumentCount
  22. 执行 SetFunctionLength(func, len)。
  23. 返回 func

10.2.4 AddRestrictedFunctionProperties ( func, realm )

The abstract operation AddRestrictedFunctionProperties takes arguments func (一个函数对象) and realm (一个 Realm Record) and returns unused. It performs the following steps when called:

  1. 断言:realm.[[Intrinsics]].[[%ThrowTypeError%]] 存在并且已经初始化。
  2. throwerrealm.[[Intrinsics]].[[%ThrowTypeError%]]。
  3. 执行 ! DefinePropertyOrThrow(func, "caller", PropertyDescriptor { [[Get]]: thrower, [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: true })。
  4. 执行 ! DefinePropertyOrThrow(func, "arguments", PropertyDescriptor { [[Get]]: thrower, [[Set]]: 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 [ , writablePrototype [ , prototype ] ] )

The abstract operation MakeConstructor takes argument func (一个 ECMAScript 函数对象或一个内建函数对象) and optional arguments writablePrototype (一个 Boolean) and prototype (一个 Object) and returns unused. 它将 func 转换为一个构造器。 It performs the following steps when called:

  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. 如果 writablePrototype 未出现,则将 writablePrototype 设为 true
  5. 如果 prototype 未出现,那么
    1. prototype 设为 OrdinaryObjectCreate(%Object.prototype%)。
    2. 执行 ! DefinePropertyOrThrow(prototype, "constructor", PropertyDescriptor { [[Value]]: func, [[Writable]]: writablePrototype, [[Enumerable]]: false, [[Configurable]]: true })。
  6. 执行 ! DefinePropertyOrThrow(func, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: writablePrototype, [[Enumerable]]: false, [[Configurable]]: false })。
  7. 返回 unused

10.2.6 MakeClassConstructor ( func )

The abstract operation MakeClassConstructor takes argument func (一个 ECMAScript 函数对象) and returns unused. It performs the following steps when called:

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

10.2.7 MakeMethod ( func, homeObject )

The abstract operation MakeMethod takes arguments func (一个 ECMAScript 函数对象) and homeObject (一个 Object) and returns unused. 它将 func 配置为一个方法。 It performs the following steps when called:

  1. 断言:homeObject 是一个普通对象
  2. func.[[HomeObject]] 设为 homeObject
  3. 返回 unused

10.2.8 DefineMethodProperty ( homeObject, key, closure, enumerable )

The abstract operation DefineMethodProperty takes arguments homeObject (一个 Object), key (一个属性键Private Name), closure (一个函数对象), and enumerable (一个 Boolean) and returns 要么是一个正常完成,包含一个 PrivateElementunused,要么是一个突然完成. It performs the following steps when called:

  1. 断言:homeObject 是一个普通的、可扩展的对象。
  2. 如果 key 是一个 Private Name,返回 PrivateElement { [[Key]]: key, [[Kind]]: method, [[Value]]: closure }。
  3. desc 为属性描述符 PropertyDescriptor { [[Value]]: closure, [[Writable]]: true, [[Enumerable]]: enumerable, [[Configurable]]: true }。
  4. 执行 ? DefinePropertyOrThrow(homeObject, key, desc)。
  5. NOTE: DefinePropertyOrThrow 仅在试图定义一个 key"prototype" 的类静态方法时才返回一个突然完成。
  6. 返回 unused

10.2.9 SetFunctionName ( func, name [ , prefix ] )

The abstract operation SetFunctionName takes arguments func (一个函数对象) and name (一个属性键Private Name) and optional argument prefix (一个 String) and returns unused. 它向 func 添加一个 "name" 属性。 It performs the following steps when called:

  1. 断言:func 是一个可扩展对象,并且没有一个 "name" 自有属性。
  2. 如果 name 是一个 Symbol,那么
    1. descriptionname.[[Description]]
    2. 如果 descriptionundefined,将 name 设为空字符串。
    3. 否则,将 name 设为 "["description"]" 的字符串串接结果。
  3. 否则如果 name 是一个 Private Name,那么
    1. name 设为 name.[[Description]]
  4. 如果 func 具有 [[InitialName]] 内部槽,那么
    1. func.[[InitialName]] 设为 name
  5. 如果 prefix 出现,那么
    1. name 设为 prefix、码元 0x0020(SPACE)与 name 的字符串串接结果。
    2. 如果 func 具有 [[InitialName]] 内部槽,那么
      1. NOTE: 以下步骤中的选择在每次调用该抽象操作时都是独立作出的。
      2. 可选地,将 func.[[InitialName]] 设为 name
  6. 执行 ! DefinePropertyOrThrow(func, "name", PropertyDescriptor { [[Value]]: name, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true })。
  7. 返回 unused

10.2.10 SetFunctionLength ( func, length )

The abstract operation SetFunctionLength takes arguments func (一个函数对象) and length (一个非负整数或 +∞) and returns unused. 它向 func 添加一个 "length" 属性。 It performs the following steps when called:

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

10.2.11 FunctionDeclarationInstantiation ( func, argumentsList )

The abstract operation FunctionDeclarationInstantiation takes arguments func (一个 ECMAScript 函数对象) and argumentsList (一个 ECMAScript 语言值列表) and returns 要么是一个正常完成,包含 unused,要么是一个抛出完成. func 是正在为其建立执行上下文函数对象

Note

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

调用时它执行以下步骤:

  1. calleeContext 为当前运行的执行上下文
  2. codefunc.[[ECMAScriptCode]]
  3. strictfunc.[[Strict]]
  4. formalsfunc.[[FormalParameters]]
  5. parameterNamesformalsBoundNames
  6. 如果 parameterNames 具有任何重复项,令 hasDuplicatestrue;否则令 hasDuplicatesfalse
  7. simpleParameterListformalsIsSimpleParameterList
  8. hasParameterExpressionsformalsContainsExpression
  9. varNamescodeVarDeclaredNames
  10. varDeclarationscodeVarScopedDeclarations
  11. lexicalNamescodeLexicallyDeclaredNames
  12. functionNames 为一个新的空列表。
  13. functionsToInitialize 为一个新的空列表。
  14. 对于 varDeclarations 中的每个元素 varDecl,按列表逆序执行,
    1. 如果 varDecl 既不是 VariableDeclaration,也不是 ForBinding,也不是 BindingIdentifier,那么
      1. 断言:varDecl 要么是 FunctionDeclaration,要么是 GeneratorDeclaration,要么是 AsyncFunctionDeclaration,要么是 AsyncGeneratorDeclaration
      2. fnvarDeclBoundNames 的唯一元素。
      3. 如果 functionNames 不包含 fn,那么
        1. fn 插入到 functionNames 的首部。
        2. NOTE: 如果同一名称有多个函数声明,则使用最后一个声明。
        3. varDecl 插入到 functionsToInitialize 的首部。
  15. argumentsObjectNeededtrue
  16. 如果 func.[[ThisMode]]lexical,那么
    1. NOTE: 箭头函数永远没有 arguments 对象。
    2. argumentsObjectNeeded 设为 false
  17. 否则如果 parameterNames 包含 "arguments",那么
    1. argumentsObjectNeeded 设为 false
  18. 否则如果 hasParameterExpressionsfalse,那么
    1. 如果 functionNames 包含 "arguments"lexicalNames 包含 "arguments",那么
      1. argumentsObjectNeeded 设为 false
  19. 如果 stricttruehasParameterExpressionsfalse,那么
    1. NOTE: 参数只需要一个 Environment Record,因为严格模式代码中的 eval 调用不能创建在 eval 外部可见的新绑定。
    2. envcalleeContext 的 LexicalEnvironment。
  20. 否则,
    1. NOTE: 需要一个单独的 Environment Record,以确保在形式参数列表中的直 接 eval 调用所创建的绑定位于参数声明所在环境之外。
    2. calleeEnvcalleeContext 的 LexicalEnvironment。
    3. envNewDeclarativeEnvironment(calleeEnv)。
    4. 断言:calleeContext 的 VariableEnvironment 与 calleeEnv 是同一个 Environment Record
    5. calleeContext 的 LexicalEnvironment 设为 env
  21. 对于 parameterNames 中的每个字符串 paramName,执行
    1. alreadyDeclared 为 ! env.HasBinding(paramName)。
    2. NOTE: 早期错误保证,重复的参数名只会出现在既非严格、又没有参数默认值、也没有剩余参数的函数中。
    3. 如果 alreadyDeclaredfalse,那么
      1. 执行 ! env.CreateMutableBinding(paramName, false)。
      2. 如果 hasDuplicatestrue,那么
        1. 执行 ! env.InitializeBinding(paramName, undefined)。
  22. 如果 argumentsObjectNeededtrue,那么
    1. 如果 stricttruesimpleParameterListfalse,那么
      1. aoCreateUnmappedArgumentsObject(argumentsList)。
    2. 否则,
      1. NOTE: 映射 arguments 对象只提供给那些非严格函数,并且它们不具有剩余参数、参数默认值初始化器或解构参数。
      2. aoCreateMappedArgumentsObject(func, formals, argumentsList, env)。
    3. 如果 stricttrue,那么
      1. 执行 ! env.CreateImmutableBinding("arguments", false)。
      2. NOTE: 在严格模式代码中,早期错误会阻止尝试给该绑定赋值,因此它的可变性是不可观察的。
    4. 否则,
      1. 执行 ! env.CreateMutableBinding("arguments", false)。
    5. 执行 ! env.InitializeBinding("arguments", ao)。
    6. parameterBindingsparameterNames 与 « "arguments" » 的列表串接。
  23. 否则,
    1. parameterBindingsparameterNames
  24. iteratorRecordCreateListIteratorRecord(argumentsList)。
  25. 如果 hasDuplicatestrue,那么
    1. usedEnvundefined
  26. 否则,
    1. usedEnvenv
  27. NOTE: 以下步骤不可能返回 ReturnCompletion,因为在表达式位置中产生此类完成的唯一方式是使用 YieldExpression,而它在参数列表中被 15.5.115.6.1早期错误规则所禁止。
  28. 执行 ? 对 formals 进行 IteratorBindingInitialization,并以 iteratorRecordusedEnv 为参数。
  29. 如果 hasParameterExpressionsfalse,那么
    1. NOTE: 参数和顶层 var 只需要一个 Environment Record
    2. instantiatedVarNames 为列表 parameterBindings 的一个副本。
    3. 对于 varNames 中的每个元素 n,执行
      1. 如果 instantiatedVarNames 不包含 n,那么
        1. n 追加到 instantiatedVarNames
        2. 执行 ! env.CreateMutableBinding(n, false)。
        3. 执行 ! env.InitializeBinding(n, undefined)。
    4. varEnvenv
  30. 否则,
    1. NOTE: 需要一个单独的 Environment Record,以确保在形式参数列表表达式中创建的闭包无法看到函数体中的声明。
    2. varEnvNewDeclarativeEnvironment(env)。
    3. calleeContext 的 VariableEnvironment 设为 varEnv
    4. instantiatedVarNames 为一个新的空列表。
    5. 对于 varNames 中的每个元素 n,执行
      1. 如果 instantiatedVarNames 不包含 n,那么
        1. n 追加到 instantiatedVarNames
        2. 执行 ! varEnv.CreateMutableBinding(n, false)。
        3. 如果 parameterBindings 不包含 nfunctionNames 包含 n,那么
          1. initialValueundefined
        4. 否则,
          1. initialValue 为 ! env.GetBindingValue(n, false)。
        5. 执行 ! varEnv.InitializeBinding(n, initialValue)。
        6. NOTE: 一个与形式参数同名的 var,其初始值与相应已初始化参数的值相同。
  31. 如果 stricttrue,那么
    1. lexEnvvarEnv
  32. 否则,
    1. Normative Optional
      如果宿主是 Web 浏览器,或以其他方式支持 块级函数声明的 Web 遗留兼容性语义,那么
      1. 对于任意 BlockCaseClauseDefaultClause x 中直接包含于其 StatementList 的每个 FunctionDeclaration fnDecl,且 code Contains xtrue,执行
        1. funcNamefnDeclBindingIdentifierStringValue
        2. 如果将 FunctionDeclaration fnDecl 替换为一个以 funcName 作为 BindingIdentifierVariableStatement 不会为 funcparameterNames 产生任何早期错误,并且 parameterNames 不包含 funcName,那么
          1. NOTE: 这里仅当 funcName 既不是 VarDeclaredName、也不是形式参数名、也不是另一个 FunctionDeclaration 的名称时,才会为其实例化一个 var 绑定。
          2. 如果 instantiatedVarNames 不包含 funcNamefuncName 不是 "arguments",那么
            1. 执行 ! varEnv.CreateMutableBinding(funcName, false)。
            2. 执行 ! varEnv.InitializeBinding(funcName, undefined)。
            3. funcName 追加到 instantiatedVarNames
          3. 当对 FunctionDeclaration fnDecl 求值时,用以下步骤替代 15.2.6 中给出的 FunctionDeclaration 求值算法:
            1. fEnv 为当前运行执行上下文的 VariableEnvironment。
            2. bEnv 为当前运行执行上下文的 LexicalEnvironment。
            3. fObj 为 ! bEnv.GetBindingValue(funcName, false)。
            4. 执行 ! fEnv.SetMutableBinding(funcName, fObj, false)。
            5. 返回 unused
    2. lexEnvNewDeclarativeEnvironment(varEnv)。
    3. NOTE: 非严格函数对顶层词法声明使用一个单独的 Environment Record,以便直接 eval 能够判断由 eval 代码引入的任何 var 作用域声明是否与预先存在的顶层词法作用域声明冲突。对于严格函数则不需要这样做,因为严格直接 eval 总是将所有声明放入一个新的 Environment Record 中。
  33. calleeContext 的 LexicalEnvironment 设为 lexEnv
  34. lexDeclarationscodeLexicallyScopedDeclarations
  35. 对于 lexDeclarations 中的每个元素 lexDecl,执行
    1. NOTE: 一个词法声明的名称不能与函数/生成器声明、形式参数或 var 名称相同。词法声明的名称只在这里被实例化,而不会被初始化。
    2. 对于 lexDeclBoundNames 中的每个元素 dn,执行
      1. 如果 lexDeclIsConstantDeclarationtrue,那么
        1. 执行 ! lexEnv.CreateImmutableBinding(dn, true)。
      2. 否则,
        1. 执行 ! lexEnv.CreateMutableBinding(dn, false)。
  36. privateEnvcalleeContext 的 PrivateEnvironment。
  37. 对于 functionsToInitialize 中的每个解析节点 fnDecl,执行
    1. fnfnDeclBoundNames 的唯一元素。
    2. fo 为对 fnDecl 执行 InstantiateFunctionObject,并以 lexEnvprivateEnv 为参数所得的结果。
    3. 执行 ! varEnv.SetMutableBinding(fn, fo, false)。
  38. 返回 unused

10.3 内建函数对象

内建函数对象是一种普通对象;它必须满足 10.1 中列出的普通对象要求。

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

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

除非另有说明,内建函数对象[[Prototype]] 内部槽的初始值为 %Function.prototype%

内建函数对象必须具有一个 [[Call]] 内部方法,其定义需符合 10.3.1 中的规定。

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

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

10.3.1 [[Call]] ( thisArgument, argumentsList )

The [[Call]] internal method of 一个内建函数对象 func takes arguments thisArgument (一个 ECMAScript 语言值) and argumentsList (一个 ECMAScript 语言值列表) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个抛出完成. It performs the following steps when called:

  1. 返回 ? BuiltinCallOrConstruct(func, thisArgument, argumentsList, undefined)。

10.3.2 [[Construct]] ( argumentsList, newTarget )

The [[Construct]] internal method of 一个内建函数对象 func(当该方法存在时) takes arguments argumentsList (一个 ECMAScript 语言值列表) and newTarget (一个构造器) and returns 要么是一个正常完成,包含一个 Object,要么是一个抛出完成. It performs the following steps when called:

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

10.3.3 BuiltinCallOrConstruct ( func, thisArgument, argumentsList, newTarget )

The abstract operation BuiltinCallOrConstruct takes arguments func (一个内建函数对象), thisArgument (一个 ECMAScript 语言值uninitialized), argumentsList (一个 ECMAScript 语言值列表), and newTarget (一个构造器undefined) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个抛出完成. It performs the following steps when called:

  1. callerContext 为当前运行的执行上下文
  2. 如果 callerContext 尚未挂起,则挂起 callerContext
  3. calleeContext 为一个新的执行上下文
  4. calleeContext 的 Function 设为 func
  5. calleeRealmfunc.[[Realm]]
  6. calleeContextRealm 设为 calleeRealm
  7. calleeContext 的 ScriptOrModule 设为 null
  8. calleeContext 执行任何必要的、由实现定义的初始化。
  9. calleeContext 压入执行上下文栈calleeContext 现在是当前运行的执行上下文
  10. 如果 func.[[Async]]true,那么
    1. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
    2. resultsClosure 为一个新的不带参数的抽象闭包,它捕获 functhisArgumentargumentsListnewTarget,并在被调用时执行以下步骤:
      1. result 为一个 Completion Record,它是以符合 func 规范的方式对 func 求值的结果。如果 thisArgumentuninitialized,则 this 值未初始化;否则 thisArgument 提供 this 值。argumentsList 提供具名参数。newTarget 提供 NewTarget 值。
      2. NOTE: 如果 func 定义于本文档中,那么“func 的规范”是指通过算法步骤或其他方式为其规定的行为。
      3. 返回 Completion(result)。
    3. 执行 AsyncFunctionStart(promiseCapability, resultsClosure)。
    4. 执行上下文栈中移除 calleeContext,并恢复 callerContext 为当前运行的执行上下文
    5. 返回 promiseCapability.[[Promise]]
  11. result 为一个 Completion Record,它是以符合 func 规范的方式对 func 求值的结果。如果 thisArgumentuninitialized,则 this 值未初始化;否则 thisArgument 提供 this 值。argumentsList 提供具名参数。newTarget 提供 NewTarget 值。
  12. NOTE: 如果 func 定义于本文档中,那么“func 的规范”是指通过算法步骤或其他方式为其规定的行为。
  13. 执行上下文栈中移除 calleeContext,并恢复 callerContext 为当前运行的执行上下文
  14. 返回 ? result
Note

calleeContext执行上下文栈中移除时,如果它已经被挂起并被一个可访问 的 Generator 保留下来以供稍后恢复,则不得销毁它。

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

The abstract operation CreateBuiltinFunction takes arguments behaviour (一个抽象闭包、一组算法步骤,或本规范中提供的某种其他函数行为定义), length (一个非负整数或 +∞), name (一个属性键或一个 Private Name), and additionalInternalSlotsList (一个内部槽名称列表) and optional arguments realm (一个 Realm Record), prototype (一个 Object 或 null), prefix (一个 String), and async (一个 Boolean) and returns 一个内建函数对象. additionalInternalSlotsList 包含必须作为该对象一部分定义的额外内部槽名 称。该操作会创建一个内建函数对象。 It performs the following steps when called:

  1. 如果 realm 未出现,则将 realm 设为当前 Realm Record
  2. 如果 prototype 未出现,则将 prototype 设为 realm.[[Intrinsics]].[[%Function.prototype%]]。
  3. 如果 async 未出现,则将 async 设为 false
  4. internalSlotsList 为一个列表,包含 10.3 要求即将创建的内建函数对象具有的所有内部槽名称。
  5. additionalInternalSlotsList 的元素追加到 internalSlotsList
  6. func 为一个新的内建函数对象,当被调用时,它会使用所提供的实参作为 behaviour 所指定的对应形参的值,执行 behaviour 所描述的动作。这个新函数对象拥有名称为 internalSlotsList 中各元素的内部槽,并且还拥有一个 [[InitialName]] 内部槽。
  7. func.[[Async]] 设为 async
  8. func.[[Prototype]] 设为 prototype
  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 中被安装。

绑定函数异质对象不具有 Table 25 中列出的 ECMAScript 函数对象内部槽。相反,它们具有 Table 26 中列出的内部槽,外加 [[Prototype]][[Extensible]]

Table 26: 绑定函数异质对象的内部槽
内部槽 类型 描述
[[BoundTargetFunction]] 一个可调用的 Object 被包装的函数对象
[[BoundThis]] 一个 ECMAScript 语言值 在调用被包装函数时,总是作为 this 值传入的值。
[[BoundArguments]] 一个 ECMAScript 语言值列表 一个值列表,其元素会作为对被包装函数的任何调用的前几个参数使用。

10.4.1.1 [[Call]] ( thisArgument, argumentsList )

The [[Call]] internal method of 一个绑定函数异质对象 func takes arguments thisArgument (一个 ECMAScript 语言值) and argumentsList (一个 ECMAScript 语言值列表) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个抛出完成. It performs the following steps when called:

  1. targetfunc.[[BoundTargetFunction]]
  2. boundThisfunc.[[BoundThis]]
  3. boundArgsfunc.[[BoundArguments]]
  4. argsboundArgsargumentsList 的列表串接。
  5. 返回 ? Call(target, boundThis, args)。

10.4.1.2 [[Construct]] ( argumentsList, newTarget )

The [[Construct]] internal method of 一个绑定函数异质对象 func takes arguments argumentsList (一个 ECMAScript 语言值列表) and newTarget (一个构造器) and returns 要么是一个正常完成,包含一个 Object,要么是一个抛出完成. It performs the following steps when called:

  1. targetfunc.[[BoundTargetFunction]]
  2. 断言:IsConstructor(target) 为 true
  3. boundArgsfunc.[[BoundArguments]]
  4. argsboundArgsargumentsList 的列表串接。
  5. 如果 SameValue(func, newTarget) 为 true,则将 newTarget 设为 target
  6. 返回 ? Construct(target, args, newTarget)。

10.4.1.3 BoundFunctionCreate ( targetFunction, boundThis, boundArgs )

The abstract operation BoundFunctionCreate takes arguments targetFunction (一个函数对象), boundThis (一个 ECMAScript 语言值), and boundArgs (一个 ECMAScript 语言值列表) and returns 要么是一个正常完成,包含一个函数对象,要么是一个抛出完成. 它用于规定新绑定函数异质对象的创建。 It performs the following steps when called:

  1. proto 为 ? targetFunction.[[GetPrototypeOf]]()
  2. internalSlotsList 为 « [[Prototype]], [[Extensible]] » 与 Table 26 中列出的内部槽的列表串接。
  3. objMakeBasicObject(internalSlotsList)。
  4. obj.[[Prototype]] 设为 proto
  5. obj.[[Call]] 设为 10.4.1.1 中规定的内容。
  6. 如果 IsConstructor(targetFunction) 为 true,那么
    1. obj.[[Construct]] 设为 10.4.1.2 中规定的内容。
  7. obj.[[BoundTargetFunction]] 设为 targetFunction
  8. obj.[[BoundThis]] 设为 boundThis
  9. obj.[[BoundArguments]] 设为 boundArgs
  10. 返回 obj

10.4.2 数组异质对象

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

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

10.4.2.1 [[DefineOwnProperty]] ( propertyKey, desc )

The [[DefineOwnProperty]] internal method of 一个数组异质对象 array takes arguments propertyKey (一个属性键) and desc (一个属性描述符) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 propertyKey"length",返回 ? ArraySetLength(array, desc)。
  2. 如果 propertyKey 是一个数组索引,那么
    1. lengthDescOrdinaryGetOwnProperty(array, "length")。
    2. 断言:lengthDesc 不为 undefined
    3. 断言:IsDataDescriptor(lengthDesc) 为 true
    4. 断言:lengthDesc.[[Configurable]]false
    5. lengthlengthDesc.[[Value]]
    6. 断言:length 是一个非负整数 Number
    7. index 为 ! ToUint32(propertyKey)。
    8. 如果 indexlengthlengthDesc.[[Writable]]false,返回 false
    9. succeeded 为 ! OrdinaryDefineOwnProperty(array, propertyKey, desc)。
    10. 如果 succeededfalse,返回 false
    11. 如果 indexlength,那么
      1. lengthDesc.[[Value]] 设为 index + 1𝔽
      2. succeeded 设为 ! OrdinaryDefineOwnProperty(array, "length", lengthDesc)。
      3. 断言:succeededtrue
    12. 返回 true
  3. 返回 ? OrdinaryDefineOwnProperty(array, propertyKey, desc)。

10.4.2.2 ArrayCreate ( length [ , proto ] )

The abstract operation ArrayCreate takes argument length (一个非负整数) and optional argument proto (一个 Object) and returns 要么是一个正常完成,包含一个数组异质对象,要么是一个抛出完成. 它用于规定新 Array 的创建。 It performs the following steps when called:

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

10.4.2.3 ArraySpeciesCreate ( originalArray, length )

The abstract operation ArraySpeciesCreate takes arguments originalArray (一个 Object) and length (一个非负整数) and returns 要么是一个正常完成,包含一个 Object,要么是一个抛出完成. 它用于规定使用从 originalArray 派生出的构造函数来创建一个新的 Array 或类似对象。它并不强制该构造函数必须返回一个 Array。 It performs the following steps when called:

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

如果 originalArray 是使用某个不等于当前运行执行上下文所属 realm 的标准 内建 Array 构造函数所创建的,那么会使用当前运行执行上下文所属 realm 来创建 一个新的 Array。这保持了与 Web 浏览器历史行为的兼容性,因为那些现如今使用 ArraySpeciesCreate 定义的 Array.prototype 方法在历史上就是如此表现的。

10.4.2.4 ArraySetLength ( array, desc )

The abstract operation ArraySetLength takes arguments array (一个 Array) and desc (一个属性描述符) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 desc 没有 [[Value]] 字段,那么
    1. 返回 ! OrdinaryDefineOwnProperty(array, "length", desc)。
  2. newLenDescdesc 的一个副本。
  3. newLen 为 ? ToUint32(desc.[[Value]])。
  4. numberLen 为 ? ToNumber(desc.[[Value]])。
  5. 如果 SameValueZero(newLen, numberLen) 为 false,抛出一个 RangeError 异常。
  6. newLenDesc.[[Value]] 设为 newLen
  7. oldLenDescOrdinaryGetOwnProperty(array, "length")。
  8. 断言:oldLenDesc 不是 undefined
  9. 断言:IsDataDescriptor(oldLenDesc) 为 true
  10. 断言:oldLenDesc.[[Configurable]]false
  11. oldLenoldLenDesc.[[Value]]
  12. 如果 newLenoldLen,那么
    1. 返回 ! OrdinaryDefineOwnProperty(array, "length", newLenDesc)。
  13. 如果 oldLenDesc.[[Writable]]false,返回 false
  14. 如果 newLenDesc 没有 [[Writable]] 字段或 newLenDesc.[[Writable]]true,那么
    1. newWritabletrue
  15. 否则,
    1. NOTE: 将 [[Writable]] 特性设为 false 会被延后,以防某些元素无法删除。
    2. newWritablefalse
    3. newLenDesc.[[Writable]] 设为 true
  16. succeeded 为 ! OrdinaryDefineOwnProperty(array, "length", newLenDesc)。
  17. 如果 succeededfalse,返回 false
  18. 对于 array 的每个自有属性键 propertyKey,若 propertyKey数组索引且 ! ToUint32(propertyKey) ≥ newLen,按数值索引降序,执行
    1. deleteSucceeded 为 ! array.[[Delete]](propertyKey)。
    2. 如果 deleteSucceededfalse,那么
      1. newLenDesc.[[Value]] 设为 ! ToUint32(propertyKey) + 1𝔽
      2. 如果 newWritablefalse,则将 newLenDesc.[[Writable]] 设为 false
      3. 执行 ! OrdinaryDefineOwnProperty(array, "length", newLenDesc)。
      4. 返回 false
  19. 如果 newWritablefalse,那么
    1. succeeded 设为 ! OrdinaryDefineOwnProperty(array, "length", PropertyDescriptor { [[Writable]]: false })。
    2. 断言:succeededtrue
  20. 返回 true
Note

在步骤 34 中,如果 desc.[[Value]] 是一个对象,则它的 valueOf 方法会被调用两次。这是一种 旧有行为,并且自本规范第 2 版起就以这种效果被规定下来。

10.4.3 字符串异质对象

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

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

字符串异质对象具有与普通对象相同的内部槽。它们还具有一个 [[StringData]] 内部槽。

10.4.3.1 [[GetOwnProperty]] ( propertyKey )

The [[GetOwnProperty]] internal method of 一个字符串异质对象 str takes argument propertyKey (一个属性键) and returns 一个正常完成,包含一个属性描述符或 undefined. It performs the following steps when called:

  1. descOrdinaryGetOwnProperty(str, propertyKey)。
  2. 如果 desc 不是 undefined,返回 desc
  3. 返回 StringGetOwnProperty(str, propertyKey)。

10.4.3.2 [[DefineOwnProperty]] ( propertyKey, desc )

The [[DefineOwnProperty]] internal method of 一个字符串异质对象 str takes arguments propertyKey (一个属性键) and desc (一个属性描述符) and returns 一个正常完成,包含一个 Boolean. It performs the following steps when called:

  1. stringDescStringGetOwnProperty(str, propertyKey)。
  2. 如果 stringDesc 不是 undefined,那么
    1. extensiblestr.[[Extensible]]
    2. 返回 IsCompatiblePropertyDescriptor(extensible, desc, stringDesc)。
  3. 返回 ! OrdinaryDefineOwnProperty(str, propertyKey, desc)。

10.4.3.3 [[OwnPropertyKeys]] ( )

The [[OwnPropertyKeys]] internal method of 一个字符串异质对象 obj takes no arguments and returns 一个正常完成,包含一个属性键列表. It performs the following steps when called:

  1. keys 为一个新的空列表。
  2. strobj.[[StringData]]
  3. 断言:str 是一个 String。
  4. lenstr 的长度。
  5. 对于每个满足 0 ≤ i < len整数 i,按升序,执行
    1. 将 ! ToString(𝔽(i)) 追加到 keys
  6. 对于 obj 的每个自有属性键 propertyKey,若 propertyKey数组索引且 ! ToIntegerOrInfinity(propertyKey) ≥ len,按数值索引升序,执行
    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, prototype )

The abstract operation StringCreate takes arguments value (一个 String) and prototype (一个 Object) and returns 一个字符串异质对象. 它用于规定新字符串异质对象的创建。 It performs the following steps when called:

  1. strMakeBasicObject[[Prototype]], [[Extensible]], [[StringData]] »)。
  2. str.[[Prototype]] 设为 prototype
  3. str.[[StringData]] 设为 value
  4. str.[[GetOwnProperty]] 设为 10.4.3.1 中规定的内容。
  5. str.[[DefineOwnProperty]] 设为 10.4.3.2 中规定的内容。
  6. str.[[OwnPropertyKeys]] 设为 10.4.3.3 中规定的内容。
  7. lengthvalue 的长度。
  8. 执行 ! DefinePropertyOrThrow(str, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false })。
  9. 返回 str

10.4.3.5 StringGetOwnProperty ( str, propertyKey )

The abstract operation StringGetOwnProperty takes arguments str (一个具有 [[StringData]] 内部槽的 Object) and propertyKey (一个属性键) and returns 一个属性描述符或 undefined. It performs the following steps when called:

  1. 如果 propertyKey 不是一个 String,返回 undefined
  2. indexCanonicalNumericIndexString(propertyKey)。
  3. 如果 index 不是一个整数 Number,返回 undefined
  4. 如果 index-0𝔽index < -0𝔽,返回 undefined
  5. stringDatastr.[[StringData]]
  6. 断言:stringData 是一个 String。
  7. lenstringData 的长度。
  8. 如果 (index) ≥ len,返回 undefined
  9. resultStrstringData 中从 (index) 到 (index) + 1 的子字符串
  10. 返回属性描述符 PropertyDescriptor { [[Value]]: resultStr, [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false }。

10.4.4 Arguments 异质对象

大多数 ECMAScript 函数都会向其代码提供一个 arguments 对象。依据函数定义的特 征不同,其 arguments 对象要么是普通对象,要么是 arguments 异质对象arguments 异质对象是一种异质对象,其数组索引属性会映射到其对应 ECMAScript 函 数某次调用的形式参数绑定。

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

Note 1

虽然 CreateUnmappedArgumentsObject 被归在本条款中,但它创建的是一个普通 对象,而不是 arguments 异质对象

arguments 异质对象具有与普通对象相同的内部槽。它们还具有一个 [[ParameterMap]] 内部槽。普通 arguments 对象也具有一个 [[ParameterMap]] 内部槽,但其值始终为 undefined。对于普通 arguments 对象而言,[[ParameterMap]] 内部槽仅由 Object.prototype.toString20.1.3.6)用来将它们识别 为 arguments 对象。

Note 2

arguments 异质对象中那些其数值名称小于对应函数对象形式参数个数的整数索引 数据属性,初始时会与函数执行上下文中的对应参数绑定共享其值。这意味着更改该 属性会更改对应参数绑定的值,反之亦然。如果这样的属性被删除后又重新定义,或者 被变更为访问器属性,则这种对应关系会被打破。如果 arguments 对象是一个普通对 象,那么其属性值只是对传入函数参数的简单拷贝,属性值与形式参数值之间不存在动 态联动。

Note 3

ParameterMap 对象及其属性值被用作一种装置,用来规定 arguments 对象与参数 绑定之间的对应关系。ParameterMap 对象以及作为其属性值的对象都不能被 ECMAScript 代码直接观察到。ECMAScript 实现并不需要实际创建或使用这类对象来实现所规定的 语义。

Note 4

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

Note 5

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

10.4.4.1 [[GetOwnProperty]] ( propertyKey )

The [[GetOwnProperty]] internal method of 一个 arguments 异质对象 args takes argument propertyKey (一个属性键) and returns 一个正常完成,包含一个属性描述符或 undefined. It performs the following steps when called:

  1. descOrdinaryGetOwnProperty(args, propertyKey)。
  2. 如果 descundefined,返回 undefined
  3. mapargs.[[ParameterMap]]
  4. isMapped 为 ! HasOwnProperty(map, propertyKey)。
  5. 如果 isMappedtrue,那么
    1. desc.[[Value]] 设为 ! Get(map, propertyKey)。
  6. 返回 desc

10.4.4.2 [[DefineOwnProperty]] ( propertyKey, desc )

The [[DefineOwnProperty]] internal method of 一个 arguments 异质对象 args takes arguments propertyKey (一个属性键) and desc (一个属性描述符) and returns 一个正常完成,包含一个 Boolean. It performs the following steps when called:

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

10.4.4.3 [[Get]] ( propertyKey, receiver )

The [[Get]] internal method of 一个 arguments 异质对象 args takes arguments propertyKey (一个属性键) and receiver (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个抛出完成. It performs the following steps when called:

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

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

The [[Set]] internal method of 一个 arguments 异质对象 args takes arguments propertyKey (一个属性键), value (一个 ECMAScript 语言值), and receiver (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

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

10.4.4.5 [[Delete]] ( propertyKey )

The [[Delete]] internal method of 一个 arguments 异质对象 args takes argument propertyKey (一个属性键) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. mapargs.[[ParameterMap]]
  2. isMapped 为 ! HasOwnProperty(map, propertyKey)。
  3. result 为 ? OrdinaryDelete(args, propertyKey)。
  4. 如果 resulttrueisMappedtrue,那么
    1. 执行 ! map.[[Delete]](propertyKey)。
  5. 返回 result

10.4.4.6 CreateUnmappedArgumentsObject ( argumentsList )

The abstract operation CreateUnmappedArgumentsObject takes argument argumentsList (一个 ECMAScript 语言值列表) and returns 一个普通对象. It performs the following steps when called:

  1. lenargumentsList 中元素的个数。
  2. objOrdinaryObjectCreate(%Object.prototype%, « [[ParameterMap]] »)。
  3. obj.[[ParameterMap]] 设为 undefined
  4. 执行 ! DefinePropertyOrThrow(obj, "length", PropertyDescriptor { [[Value]]: 𝔽(len), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true })。
  5. index 为 0。
  6. 重复,当 index < len 时,
    1. valargumentsList[index]。
    2. 执行 ! CreateDataPropertyOrThrow(obj, ! ToString(𝔽(index)), val)。
    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 { [[Get]]: %ThrowTypeError%, [[Set]]: %ThrowTypeError%, [[Enumerable]]: false, [[Configurable]]: false })。
  9. 返回 obj

10.4.4.7 CreateMappedArgumentsObject ( func, formals, argumentsList, env )

The abstract operation CreateMappedArgumentsObject takes arguments func (an ECMAScript function object), formals (a Parse Node), argumentsList (a List of ECMAScript language values), and env (an Environment Record) and returns an arguments exotic object. It performs the following steps when called:

  1. 断言:formals 不包含剩余参数、任何绑定模式或任何初始化器。它可以包含重复的标识符。
  2. lenargumentsList 中元素的个数。
  3. objMakeBasicObject[[Prototype]], [[Extensible]], [[ParameterMap]] »)。
  4. obj.[[GetOwnProperty]] 设为 10.4.4.1 中规定的内容。
  5. obj.[[DefineOwnProperty]] 设为 10.4.4.2 中规定的内容。
  6. obj.[[Get]] 设为 10.4.4.3 中规定的内容。
  7. obj.[[Set]] 设为 10.4.4.4 中规定的内容。
  8. obj.[[Delete]] 设为 10.4.4.5 中规定的内容。
  9. obj.[[Prototype]] 设为 %Object.prototype%
  10. mapOrdinaryObjectCreate(null)。
  11. obj.[[ParameterMap]] 设为 map
  12. parameterNamesformalsBoundNames
  13. numberOfParametersparameterNames 中元素的个数。
  14. index 为 0。
  15. 重复,当 index < len 时,
    1. valargumentsList[index]。
    2. 执行 ! CreateDataPropertyOrThrow(obj, ! ToString(𝔽(index)), val)。
    3. index 设为 index + 1。
  16. 执行 ! DefinePropertyOrThrow(obj, "length", PropertyDescriptor { [[Value]]: 𝔽(len), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true })。
  17. mappedNames 为一个新的空列表。
  18. index 设为 numberOfParameters - 1。
  19. 重复,当 index ≥ 0 时,
    1. nameparameterNames[index]。
    2. 如果 mappedNames 不包含 name,那么
      1. name 追加到 mappedNames
      2. 如果 index < len,那么
        1. getterMakeArgGetter(name, env)。
        2. setterMakeArgSetter(name, env)。
        3. 执行 ! map.[[DefineOwnProperty]](! ToString(𝔽(index)), PropertyDescriptor { [[Set]]: setter, [[Get]]: 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, env )

The abstract operation MakeArgGetter takes arguments name (一个 String) and env (一个 Environment Record) and returns 一个函数对象. 它会创建一个内建函数对象,该对象在执行时返回 env 中绑定到 name 的值。 It performs the following steps when called:

  1. getterClosure 为一个新的不带参数的抽象闭包,它捕获 nameenv,并在被调用时执行以下步骤:
    1. 返回 NormalCompletion(! env.GetBindingValue(name, false))。
  2. getterCreateBuiltinFunction(getterClosure, 0, "", « »)。
  3. NOTE: getter 永远不能被 ECMAScript 代码直接访问。
  4. 返回 getter

10.4.4.7.2 MakeArgSetter ( name, env )

The abstract operation MakeArgSetter takes arguments name (一个 String) and env (一个 Environment Record) and returns 一个函数对象. 它会创建一个内建函数对象,该对象在执行时将 env 中绑定到 name 的值设为给定值。 It performs the following steps when called:

  1. setterClosure 为一个带参数 (value) 的新抽象闭包,它捕获 nameenv,并在被调用时执行以下步骤:
    1. 返回 NormalCompletion(! env.SetMutableBinding(name, value, false))。
  2. setterCreateBuiltinFunction(setterClosure, 1, "", « »)。
  3. NOTE: setter 永远不能被 ECMAScript 代码直接访问。
  4. 返回 setter

10.4.5 TypedArray 异质对象

TypedArray 是一种异质对象,它会对作为规范数值字符串canonical numeric strings) 的属性键进行特殊处理,使用其中属于边界内整数索引的那一部分来索引统一类型的元 素,并强制保证其余那些键不存在,且不会引发原型链遍历。

Note

由于对于任意 Number nToString(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]] ( )

The [[PreventExtensions]] internal method of 一个 TypedArray obj takes no arguments and returns 一个正常完成,包含一个 Boolean. It performs the following steps when called:

  1. NOTE: 6.1.7.3 中规定的与可扩展性相关的不变量不允许当 obj 仍可能获得(或失去后再次获 得)属性时该方法返回 true;而这类情况可能会发生在其底层缓冲区被调整大 小时,具有整数索引名称的属性上。
  2. 如果 IsTypedArrayFixedLength(obj) 为 false,返回 false
  3. 返回 OrdinaryPreventExtensions(obj)。

10.4.5.2 [[GetOwnProperty]] ( propertyKey )

The [[GetOwnProperty]] internal method of 一个 TypedArray obj takes argument propertyKey (一个属性键) and returns 一个正常完成,包含一个属性描述符或 undefined. It performs the following steps when called:

  1. 如果 propertyKey 是一个 String,那么
    1. numericIndexCanonicalNumericIndexString(propertyKey)。
    2. 如果 numericIndex 不是 undefined,那么
      1. valueTypedArrayGetElement(obj, numericIndex)。
      2. 如果 valueundefined,返回 undefined
      3. 返回属性描述符 PropertyDescriptor { [[Value]]: value, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }。
  2. 返回 OrdinaryGetOwnProperty(obj, propertyKey)。

10.4.5.3 [[HasProperty]] ( propertyKey )

The [[HasProperty]] internal method of 一个 TypedArray obj takes argument propertyKey (一个属性键) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 propertyKey 是一个 String,那么
    1. numericIndexCanonicalNumericIndexString(propertyKey)。
    2. 如果 numericIndex 不是 undefined,返回 IsValidIntegerIndex(obj, numericIndex)。
  2. 返回 ? OrdinaryHasProperty(obj, propertyKey)。

10.4.5.4 [[DefineOwnProperty]] ( propertyKey, desc )

The [[DefineOwnProperty]] internal method of 一个 TypedArray obj takes arguments propertyKey (一个属性键) and desc (一个属性描述符) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

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

10.4.5.5 [[Get]] ( propertyKey, receiver )

The [[Get]] internal method of 一个 TypedArray obj takes arguments propertyKey (一个属性键) and receiver (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 propertyKey 是一个 String,那么
    1. numericIndexCanonicalNumericIndexString(propertyKey)。
    2. 如果 numericIndex 不是 undefined,那么
      1. 返回 TypedArrayGetElement(obj, numericIndex)。
  2. 返回 ? OrdinaryGet(obj, propertyKey, receiver)。

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

The [[Set]] internal method of 一个 TypedArray obj takes arguments propertyKey (一个属性键), value (一个 ECMAScript 语言值), and receiver (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 propertyKey 是一个 String,那么
    1. numericIndexCanonicalNumericIndexString(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 )

The [[Delete]] internal method of 一个 TypedArray obj takes argument propertyKey (一个属性键) and returns 一个正常完成,包含一个 Boolean. It performs the following steps when called:

  1. 如果 propertyKey 是一个 String,那么
    1. numericIndexCanonicalNumericIndexString(propertyKey)。
    2. 如果 numericIndex 不是 undefined,那么
      1. 如果 IsValidIntegerIndex(obj, numericIndex) 为 false,返回 true
      2. 返回 false
  2. 返回 ! OrdinaryDelete(obj, propertyKey)。

10.4.5.8 [[OwnPropertyKeys]] ( )

The [[OwnPropertyKeys]] internal method of 一个 TypedArray obj takes no arguments and returns 一个正常完成,包含一个属性键列表. It performs the following steps when called:

  1. taRecordMakeTypedArrayWithBufferWitnessRecord(obj, seq-cst)。
  2. keys 为一个新的空列表。
  3. 如果 IsTypedArrayOutOfBounds(taRecord) 为 false,那么
    1. lengthTypedArrayLength(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

带缓冲区见证记录的 TypedArray 是一种记录值,用于封装一个 TypedArray 以及其所查看缓冲区的一个缓存字节长度。 当该查看缓冲区是一个可增长的 SharedArrayBuffer 时,它用于帮助确保字节长度数 据块只有一次 ReadSharedMemory 事件。

带缓冲区见证记录的 TypedArray 具有 Table 27 中列出的字段。

Table 27: 带缓冲区见证记录的 TypedArray 字段
字段名 含义
[[Object]] 一个 TypedArray 其缓冲区字节长度被加载的那个 TypedArray
[[CachedBufferByteLength]] 一个非负整数detached 创建该记录时,对象的 [[ViewedArrayBuffer]] 的字节长度。

10.4.5.10 MakeTypedArrayWithBufferWitnessRecord ( obj, order )

The abstract operation MakeTypedArrayWithBufferWitnessRecord takes arguments obj (一个 TypedArray) and order (seq-cstunordered) and returns 一个带缓冲区见证记录的 TypedArray. It performs the following steps when called:

  1. bufferobj.[[ViewedArrayBuffer]]
  2. 如果 IsDetachedBuffer(buffer) 为 true,那么
    1. byteLengthdetached
  3. 否则,
    1. byteLengthArrayBufferByteLength(buffer, order)。
  4. 返回带缓冲区见证记录的 TypedArray { [[Object]]: obj, [[CachedBufferByteLength]]: byteLength }。

10.4.5.11 TypedArrayCreate ( prototype )

The abstract operation TypedArrayCreate takes argument prototype (一个 Object) and returns 一个 TypedArray. 它用于规定新 TypedArray 的创建。 It performs the following steps when called:

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

10.4.5.12 TypedArrayByteLength ( taRecord )

The abstract operation TypedArrayByteLength takes argument taRecord (一个带缓冲区见证记录的 TypedArray) and returns 一个非负整数. It performs the following steps when called:

  1. 断言:IsTypedArrayOutOfBounds(taRecord) 为 false
  2. objtaRecord.[[Object]]
  3. 如果 obj.[[ByteLength]] 不是 auto,返回 obj.[[ByteLength]]
  4. lengthTypedArrayLength(taRecord)。
  5. elementSizeTypedArrayElementSize(obj)。
  6. NOTE: 返回的字节长度始终是 elementSize整数倍,即便底层缓冲区已被调整为非整数倍长度。
  7. 返回 length × elementSize

10.4.5.13 TypedArrayLength ( taRecord )

The abstract operation TypedArrayLength takes argument taRecord (一个带缓冲区见证记录的 TypedArray) and returns 一个非负整数. It performs the following steps when called:

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

10.4.5.14 IsTypedArrayOutOfBounds ( taRecord )

The abstract operation IsTypedArrayOutOfBounds takes argument taRecord (一个带缓冲区见证记录的 TypedArray) and returns 一个 Boolean. 它检查对象的任何数值属性是否会引用到底层缓冲区边界之外某个索引处的值。 It performs the following steps when called:

  1. objtaRecord.[[Object]]
  2. bufferByteLengthtaRecord.[[CachedBufferByteLength]]
  3. 如果 IsDetachedBuffer(obj.[[ViewedArrayBuffer]]) 为 true,那么
    1. 断言:bufferByteLengthdetached
    2. 返回 true
  4. 断言:bufferByteLength 是一个非负整数
  5. byteOffsetStartobj.[[ByteOffset]]
  6. 如果 obj.[[ArrayLength]]auto,那么
    1. byteOffsetEndbufferByteLength
  7. 否则,
    1. elementSizeTypedArrayElementSize(obj)。
    2. arrayByteLengthobj.[[ArrayLength]] × elementSize
    3. byteOffsetEndbyteOffsetStart + arrayByteLength
  8. NOTE: 一个长度为 0 且其 [[ByteOffset]] 等于 bufferByteLengthTypedArray 不被视为越界。
  9. 如果 byteOffsetStart > bufferByteLengthbyteOffsetEnd > bufferByteLength,返回 true
  10. 返回 false

10.4.5.15 IsTypedArrayFixedLength ( obj )

The abstract operation IsTypedArrayFixedLength takes argument obj (一个 TypedArray) and returns 一个 Boolean. It performs the following steps when called:

  1. 如果 obj.[[ArrayLength]]auto,返回 false
  2. bufferobj.[[ViewedArrayBuffer]]
  3. 如果 IsFixedLengthArrayBuffer(buffer) 为 falseIsSharedArrayBuffer(buffer) 为 false,返回 false
  4. 返回 true

10.4.5.16 IsValidIntegerIndex ( obj, index )

The abstract operation IsValidIntegerIndex takes arguments obj (一个 TypedArray) and index (一个 Number) and returns 一个 Boolean. It performs the following steps when called:

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

10.4.5.17 TypedArrayGetElement ( obj, index )

The abstract operation TypedArrayGetElement takes arguments obj (一个 TypedArray) and index (一个 Number) and returns 一个 Number、一个 BigInt 或 undefined. It performs the following steps when called:

  1. 如果 IsValidIntegerIndex(obj, index) 为 false,返回 undefined
  2. offsetobj.[[ByteOffset]]
  3. elementSizeTypedArrayElementSize(obj)。
  4. byteIndexInBuffer 为 ((index) × elementSize) + offset
  5. elementTypeTypedArrayElementType(obj)。
  6. 返回 GetValueFromBuffer(obj.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, true, unordered)。

10.4.5.18 TypedArraySetElement ( obj, index, value )

The abstract operation TypedArraySetElement takes arguments obj (一个 TypedArray), index (一个 Number), and value (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含 unused,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 obj.[[ContentType]]bigint,令 numValue 为 ? ToBigInt(value)。
  2. 否则,令 numValue 为 ? ToNumber(value)。
  3. 如果 IsValidIntegerIndex(obj, index) 为 true,那么
    1. offsetobj.[[ByteOffset]]
    2. elementSizeTypedArrayElementSize(obj)。
    3. byteIndexInBuffer 为 ((index) × elementSize) + offset
    4. elementTypeTypedArrayElementType(obj)。
    5. 执行 SetValueInBuffer(obj.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, numValue, true, unordered)。
  4. 返回 unused
Note

该操作总是看起来会成功,但当尝试写入 TypedArray 末尾之外的位置,或写入一 个由已分离的 ArrayBuffer 支持的 TypedArray 时,它实际上不会产生效果。

10.4.5.19 IsArrayBufferViewOutOfBounds ( obj )

The abstract operation IsArrayBufferViewOutOfBounds takes argument obj (一个 TypedArray 或一个 DataView) and returns 一个 Boolean. 它检查 TypedArray 的任何数值属性或 DataView 对象的方法是否能够引用到底 层数据块边界之外某个索引处的值。该抽象操作作为对上游规范的一种便利而存在。 It performs the following steps when called:

  1. 如果 obj 具有 [[DataView]] 内部槽,那么
    1. viewRecordMakeDataViewWithBufferWitnessRecord(obj, seq-cst)。
    2. 返回 IsViewOutOfBounds(viewRecord)。
  2. taRecordMakeTypedArrayWithBufferWitnessRecord(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 中被安装。

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

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

10.4.6.1 [[GetPrototypeOf]] ( )

The [[GetPrototypeOf]] internal method of 一个模块命名空间异质对象 takes no arguments and returns 一个正常完成,包含 null. It performs the following steps when called:

  1. 返回 null

10.4.6.2 [[SetPrototypeOf]] ( proto )

The [[SetPrototypeOf]] internal method of 一个模块命名空间异质对象 obj takes argument proto (一个 Object 或 null) and returns 一个正常完成,包含一个 Boolean. It performs the following steps when called:

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

10.4.6.3 [[IsExtensible]] ( )

The [[IsExtensible]] internal method of 一个模块命名空间异质对象 takes no arguments and returns 一个正常完成,包含 false. It performs the following steps when called:

  1. 返回 false

10.4.6.4 [[PreventExtensions]] ( )

The [[PreventExtensions]] internal method of 一个模块命名空间异质对象 takes no arguments and returns 一个正常完成,包含 true. It performs the following steps when called:

  1. 返回 true

10.4.6.5 [[GetOwnProperty]] ( propertyKey )

The [[GetOwnProperty]] internal method of 一个模块命名空间异质对象 obj takes argument propertyKey (一个属性键) and returns 要么是一个正常完成,包含一个属性描述符或 undefined,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 propertyKey 是一个 Symbol,返回 OrdinaryGetOwnProperty(obj, propertyKey)。
  2. exportsobj.[[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, desc )

The [[DefineOwnProperty]] internal method of 一个模块命名空间异质对象 obj takes arguments propertyKey (一个属性键) and desc (一个属性描述符) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

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

10.4.6.7 [[HasProperty]] ( propertyKey )

The [[HasProperty]] internal method of 一个模块命名空间异质对象 obj takes argument propertyKey (一个属性键) and returns 一个正常完成,包含一个 Boolean. It performs the following steps when called:

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

10.4.6.8 [[Get]] ( propertyKey, receiver )

The [[Get]] internal method of 一个模块命名空间异质对象 obj takes arguments propertyKey (一个属性键) and receiver (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个抛出完成. It performs the following steps when called:

  1. 如果 propertyKey 是一个 Symbol,那么
    1. 返回 ! OrdinaryGet(obj, propertyKey, receiver)。
  2. exportsobj.[[Exports]]
  3. 如果 exports 不包含 propertyKey,返回 undefined
  4. moduleobj.[[Module]]
  5. bindingmodule.ResolveExport(propertyKey)。
  6. 断言:binding 是一个 ResolvedBinding Record
  7. targetModulebinding.[[Module]]
  8. 断言:targetModule 不是 undefined
  9. 如果 binding.[[BindingName]]namespace,那么
    1. 返回 GetModuleNamespace(targetModule)。
  10. targetEnvtargetModule.[[Environment]]
  11. 如果 targetEnvempty,抛出一个 ReferenceError 异常。
  12. 返回 ? targetEnv.GetBindingValue(binding.[[BindingName]], true)。
Note

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

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

The [[Set]] internal method of 一个模块命名空间异质对象 takes arguments propertyKey (一个属性键), value (一个 ECMAScript 语言值), and receiver (一个 ECMAScript 语言值) and returns 一个正常完成,包含 false. It performs the following steps when called:

  1. 返回 false

10.4.6.10 [[Delete]] ( propertyKey )

The [[Delete]] internal method of 一个模块命名空间异质对象 obj takes argument propertyKey (一个属性键) and returns 一个正常完成,包含一个 Boolean. It performs the following steps when called:

  1. 如果 propertyKey 是一个 Symbol,那么
    1. 返回 ! OrdinaryDelete(obj, propertyKey)。
  2. exportsobj.[[Exports]]
  3. 如果 exports 包含 propertyKey,返回 false
  4. 返回 true

10.4.6.11 [[OwnPropertyKeys]] ( )

The [[OwnPropertyKeys]] internal method of 一个模块命名空间异质对象 obj takes no arguments and returns 一个正常完成,包含一个属性键列表. It performs the following steps when called:

  1. exportsobj.[[Exports]]
  2. symbolKeysOrdinaryOwnPropertyKeys(obj)。
  3. 返回 exportssymbolKeys 的列表串接。

10.4.6.12 ModuleNamespaceCreate ( module, exports )

The abstract operation ModuleNamespaceCreate takes arguments module (一个 Module Record) and exports (一个 String 列表) and returns 一个模块命名空间异质对象. 它用于规定新模块命名空间异质对象的创建。 It performs the following steps when called:

  1. 断言:module.[[Namespace]]empty
  2. internalSlotsListTable 28 中列出的内部槽。
  3. namespaceMakeBasicObject(internalSlotsList)。
  4. namespace 的基本内部方法设为 10.4.6 中规定的定义。
  5. namespace.[[Module]] 设为 module
  6. sortedExports 为一个列表,其元素是 exports 的元素,并按词法码元顺序排序。
  7. namespace.[[Exports]] 设为 sortedExports
  8. 根据 28.3 中的定义在 namespace 上创建自有属性。
  9. module.[[Namespace]] 设为 namespace
  10. 返回 namespace

10.4.7 不可变原型异质对象

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

如果一个对象的 [[SetPrototypeOf]] 内部方法使用以下实现,则该对象是一个 不可变原型异质对象。 (至于它的其他基本内部方法可以采用何种实现,则取决于具体的不可变原型异质对象。)

Note

与其他异质对象不同,并没有为不可变原型异质对象提供专门的创建抽象操作。这是 因为它们只被 %Object.prototype%宿主环境使用;而在宿主环境中,相关对象可能 还会以其他方式表现为异质,因此需要它们自己的专门创建操作。

10.4.7.1 [[SetPrototypeOf]] ( proto )

The [[SetPrototypeOf]] internal method of 一个不可变原型异质对象 obj takes argument proto (一个 Object 或 null) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

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

10.4.7.2 SetImmutablePrototype ( obj, proto )

The abstract operation SetImmutablePrototype takes arguments obj (一个 Object) and proto (一个 Object 或 null) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

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

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

Proxy 对象是一种异质对象,其基本内部方法的一部分使用 ECMAScript 代码实现。 每个 Proxy 对象都有一个名为 [[ProxyHandler]] 的内部槽。[[ProxyHandler]] 的值 是一个对象,称为该 proxy 的处理器对象,或者是 null。处理器对象 的方法(见 Table 29)可 以用来增强 Proxy 对象的一个或多个内部方法的实现。每个 Proxy 对象还有一个名 为 [[ProxyTarget]] 的内部槽,其值要么是一个对象,要么是 null。这个对象 被称为该 proxy 的目标对象

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

Table 29: 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 的目标对象作为参数传入。proxy 的处理器对象不一定具有与每个基本内部 方法对应的方法。如果处理器对象没有与该内部陷阱对应的方法,那么在 proxy 上调 用某个内部方法,会导致在 proxy 的目标对象上调用相应的内部方法。

Proxy 对象的 [[ProxyHandler]][[ProxyTarget]] 内部槽在对象创建时总是 被初始化,并且通常不可修改。某些 Proxy 对象会以一种允许其后续被撤销 的方式创建。当一个 proxy 被撤销时,它的 [[ProxyHandler]][[ProxyTarget]] 内部槽都会被设为 null,从而导致之后对该 Proxy 对象内部方法的调用抛出一个 TypeError 异常。

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

在以下算法描述中,假设 obj 是一个 ECMAScript Proxy 对象,propertyKey 是一个属性键值,value 是任意 ECMAScript 语言值desc 是一个属性描述符记 录。

10.5.1 [[GetPrototypeOf]] ( )

The [[GetPrototypeOf]] internal method of 一个 Proxy 异质对象 obj takes no arguments and returns 要么是一个正常完成,包含一个 Object 或 null,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是一个 Object。
  5. trap 为 ? GetMethod(handler, "getPrototypeOf")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[GetPrototypeOf]]()
  7. handlerProto 为 ? Call(trap, handler, « target »)。
  8. 如果 handlerProto 既不是一个 Object 也不是 null,抛出一个 TypeError 异常。
  9. extensibleTarget 为 ? IsExtensible(target)。
  10. 如果 extensibleTargettrue,返回 handlerProto
  11. targetProto 为 ? target.[[GetPrototypeOf]]()
  12. 如果 SameValue(handlerProto, targetProto) 为 false,抛出一个 TypeError 异常。
  13. 返回 handlerProto
Note

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

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

10.5.2 [[SetPrototypeOf]] ( proto )

The [[SetPrototypeOf]] internal method of 一个 Proxy 异质对象 obj takes argument proto (一个 Object 或 null) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是一个 Object。
  5. trap 为 ? GetMethod(handler, "setPrototypeOf")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[SetPrototypeOf]](proto)
  7. booleanTrapResultToBoolean(? Call(trap, handler, « target, proto »))。
  8. 如果 booleanTrapResultfalse,返回 false
  9. extensibleTarget 为 ? IsExtensible(target)。
  10. 如果 extensibleTargettrue,返回 true
  11. targetProto 为 ? target.[[GetPrototypeOf]]()
  12. 如果 SameValue(proto, targetProto) 为 false,抛出一个 TypeError 异常。
  13. 返回 true
Note

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

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

10.5.3 [[IsExtensible]] ( )

The [[IsExtensible]] internal method of 一个 Proxy 异质对象 obj takes no arguments and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是一个 Object。
  5. trap 为 ? GetMethod(handler, "isExtensible")。
  6. 如果 trapundefined,那么
    1. 返回 ? IsExtensible(target)。
  7. booleanTrapResultToBoolean(? Call(trap, handler, « target »))。
  8. targetResult 为 ? IsExtensible(target)。
  9. 如果 booleanTrapResult 不等于 targetResult,抛出一个 TypeError 异常。
  10. 返回 booleanTrapResult
Note

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

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

10.5.4 [[PreventExtensions]] ( )

The [[PreventExtensions]] internal method of 一个 Proxy 异质对象 obj takes no arguments and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是一个 Object。
  5. trap 为 ? GetMethod(handler, "preventExtensions")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[PreventExtensions]]()
  7. booleanTrapResultToBoolean(? Call(trap, handler, « target »))。
  8. 如果 booleanTrapResulttrue,那么
    1. extensibleTarget 为 ? IsExtensible(target)。
    2. 如果 extensibleTargettrue,抛出一个 TypeError 异常。
  9. 返回 booleanTrapResult
Note

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

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

10.5.5 [[GetOwnProperty]] ( propertyKey )

The [[GetOwnProperty]] internal method of 一个 Proxy 异质对象 obj takes argument propertyKey (一个属性键) and returns 要么是一个正常完成,包含一个属性描述符或 undefined,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是一个 Object。
  5. trap 为 ? GetMethod(handler, "getOwnPropertyDescriptor")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[GetOwnProperty]](propertyKey)
  7. trapResultObj 为 ? Call(trap, handler, « target, propertyKey »)。
  8. 如果 trapResultObj 既不是一个 Object 也不是 undefined,抛出一个 TypeError 异常。
  9. targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)
  10. 如果 trapResultObjundefined,那么
    1. 如果 targetDescundefined,返回 undefined
    2. 如果 targetDesc.[[Configurable]]false,抛出一个 TypeError 异常。
    3. extensibleTarget 为 ? IsExtensible(target)。
    4. 如果 extensibleTargetfalse,抛出一个 TypeError 异常。
    5. 返回 undefined
  11. extensibleTarget 为 ? IsExtensible(target)。
  12. resultDesc 为 ? ToPropertyDescriptor(trapResultObj)。
  13. 执行 CompletePropertyDescriptor(resultDesc)。
  14. validIsCompatiblePropertyDescriptor(extensibleTarget, resultDesc, targetDesc)。
  15. 如果 validfalse,抛出一个 TypeError 异常。
  16. 如果 resultDesc.[[Configurable]]false,那么
    1. 如果 targetDescundefinedtargetDesc.[[Configurable]]true,那么
      1. 抛出一个 TypeError 异常。
    2. 如果 resultDesc 具有 [[Writable]] 字段且 resultDesc.[[Writable]]false,那么
      1. 断言:targetDesc 具有 [[Writable]] 字段。
      2. 如果 targetDesc.[[Writable]]true,抛出一个 TypeError 异常。
  17. 返回 resultDesc
Note

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

  • [[GetOwnProperty]] 的结果必须是一个属性描述符或 undefined
  • 如果某个属性作为目标对象的一个不可配置自有属性存在,则不能将其报告为不存在。
  • 如果某个属性作为不可扩展目标对象的一个自有属性存在,则不能将其报告为不存在。
  • 如果某个属性不是目标对象的自有属性,且目标对象不可扩展,则不能将其报告为存在。
  • 除非目标对象上存在一个对应的不可配置自有属性,否则不能将某个属性报告为不可配置。
  • 除非目标对象上存在一个对应的不可配置且不可写的自有属性,否则不能将某个属性同时报告为不可配置且不可写。

10.5.6 [[DefineOwnProperty]] ( propertyKey, desc )

The [[DefineOwnProperty]] internal method of 一个 Proxy 异质对象 obj takes arguments propertyKey (一个属性键) and desc (一个属性描述符) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是一个 Object。
  5. trap 为 ? GetMethod(handler, "defineProperty")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[DefineOwnProperty]](propertyKey, desc)
  7. descObjFromPropertyDescriptor(desc)。
  8. booleanTrapResultToBoolean(? Call(trap, handler, « target, propertyKey, descObj »))。
  9. 如果 booleanTrapResultfalse,返回 false
  10. targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)
  11. extensibleTarget 为 ? IsExtensible(target)。
  12. 如果 desc 具有 [[Configurable]] 字段且 desc.[[Configurable]]false,那么
    1. settingConfigFalsetrue
  13. 否则,
    1. settingConfigFalsefalse
  14. 如果 targetDescundefined,那么
    1. 如果 extensibleTargetfalse,抛出一个 TypeError 异常。
    2. 如果 settingConfigFalsetrue,抛出一个 TypeError 异常。
  15. 否则,
    1. 如果 IsCompatiblePropertyDescriptor(extensibleTarget, desc, targetDesc) 为 false,抛出一个 TypeError 异常。
    2. 如果 settingConfigFalsetruetargetDesc.[[Configurable]]true,抛出一个 TypeError 异常。
    3. 如果 IsDataDescriptor(targetDesc) 为 truetargetDesc.[[Configurable]]false,并且 targetDesc.[[Writable]]true,那么
      1. 如果 desc 具有 [[Writable]] 字段且 desc.[[Writable]]false,抛出一个 TypeError 异常。
  16. 返回 true
Note

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

  • [[DefineOwnProperty]] 的结果是一个 Boolean 值。
  • 如果目标对象不可扩展,则不能添加属性。
  • 除非目标对象上存在一个对应的不可配置自有属性,否则某个属性不能是不可配置的。
  • 除非目标对象上存在一个对应的不可配置且不可写的自有属性,否则不可配置属性不能是不可写的。
  • 如果某个属性在目标对象上有对应属性,那么将该属性的属性描述符应用到目标对象 并使用 [[DefineOwnProperty]] 时,不得抛出异常。

10.5.7 [[HasProperty]] ( propertyKey )

The [[HasProperty]] internal method of 一个 Proxy 异质对象 obj takes argument propertyKey (一个属性键) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是一个 Object。
  5. trap 为 ? GetMethod(handler, "has")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[HasProperty]](propertyKey)
  7. booleanTrapResultToBoolean(? Call(trap, handler, « target, propertyKey »))。
  8. 如果 booleanTrapResultfalse,那么
    1. targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)
    2. 如果 targetDesc 不是 undefined,那么
      1. 如果 targetDesc.[[Configurable]]false,抛出一个 TypeError 异常。
      2. extensibleTarget 为 ? IsExtensible(target)。
      3. 如果 extensibleTargetfalse,抛出一个 TypeError 异常。
  9. 返回 booleanTrapResult
Note

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

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

10.5.8 [[Get]] ( propertyKey, receiver )

The [[Get]] internal method of 一个 Proxy 异质对象 obj takes arguments propertyKey (一个属性键) and receiver (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是一个 Object。
  5. trap 为 ? GetMethod(handler, "get")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[Get]](propertyKey, receiver)
  7. trapResult 为 ? Call(trap, handler, « target, propertyKey, receiver »)。
  8. targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)
  9. 如果 targetDesc 不是 undefinedtargetDesc.[[Configurable]]false,那么
    1. 如果 IsDataDescriptor(targetDesc) 为 truetargetDesc.[[Writable]]false,那么
      1. 如果 SameValue(trapResult, targetDesc.[[Value]]) 为 false,抛出一个 TypeError 异常。
    2. 如果 IsAccessorDescriptor(targetDesc) 为 truetargetDesc.[[Get]]undefined,那么
      1. 如果 trapResult 不是 undefined,抛出一个 TypeError 异常。
  10. 返回 trapResult
Note

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

  • 如果目标对象上的对应属性是一个不可写、不可配置的自有数据属性,那么某属性 所报告的值必须与该对应目标对象属性的值相同。
  • 如果目标对象上的对应属性是一个不可配置的自有访问器属性,且其 [[Get]] 特 性为 undefined,那么该属性所报告的值必须是 undefined

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

The [[Set]] internal method of 一个 Proxy 异质对象 obj takes arguments propertyKey (一个属性键), value (一个 ECMAScript 语言值), and receiver (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是一个 Object。
  5. trap 为 ? GetMethod(handler, "set")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[Set]](propertyKey, value, receiver)
  7. booleanTrapResultToBoolean(? Call(trap, handler, « target, propertyKey, value, receiver »))。
  8. 如果 booleanTrapResultfalse,返回 false
  9. targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)
  10. 如果 targetDesc 不是 undefinedtargetDesc.[[Configurable]]false,那么
    1. 如果 IsDataDescriptor(targetDesc) 为 truetargetDesc.[[Writable]]false,那么
      1. 如果 SameValue(value, targetDesc.[[Value]]) 为 false,抛出一个 TypeError 异常。
    2. 如果 IsAccessorDescriptor(targetDesc) 为 true,那么
      1. 如果 targetDesc.[[Set]]undefined,抛出一个 TypeError 异常。
  11. 返回 true
Note

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

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

10.5.10 [[Delete]] ( propertyKey )

The [[Delete]] internal method of 一个 Proxy 异质对象 obj takes argument propertyKey (一个属性键) and returns 要么是一个正常完成,包含一个 Boolean,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是一个 Object。
  5. trap 为 ? GetMethod(handler, "deleteProperty")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[Delete]](propertyKey)
  7. booleanTrapResultToBoolean(? Call(trap, handler, « target, propertyKey »))。
  8. 如果 booleanTrapResultfalse,返回 false
  9. targetDesc 为 ? target.[[GetOwnProperty]](propertyKey)
  10. 如果 targetDescundefined,返回 true
  11. 如果 targetDesc.[[Configurable]]false,抛出一个 TypeError 异常。
  12. extensibleTarget 为 ? IsExtensible(target)。
  13. 如果 extensibleTargetfalse,抛出一个 TypeError 异常。
  14. 返回 true
Note

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

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

10.5.11 [[OwnPropertyKeys]] ( )

The [[OwnPropertyKeys]] internal method of 一个 Proxy 异质对象 obj takes no arguments and returns 要么是一个正常完成,包含一个属性键列表,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是一个 Object。
  5. trap 为 ? GetMethod(handler, "ownKeys")。
  6. 如果 trapundefined,那么
    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 是一个属性键列表。
  13. 断言:targetKeys 不包含重复项。
  14. targetConfigurableKeys 为一个新的空列表。
  15. targetNonconfigurableKeys 为一个新的空列表。
  16. 对于 targetKeys 中的每个元素 key,执行
    1. desc 为 ? target.[[GetOwnProperty]](key)
    2. 如果 desc 不是 undefineddesc.[[Configurable]]false,那么
      1. key 追加到 targetNonconfigurableKeys
    3. 否则,
      1. key 追加到 targetConfigurableKeys
  17. 如果 extensibleTargettruetargetNonconfigurableKeys 为空,那么
    1. 返回 trapResult
  18. uncheckedResultKeys 为一个列表,其元素为 trapResult 的各元素。
  19. 对于 targetNonconfigurableKeys 中的每个元素 key,执行
    1. 如果 uncheckedResultKeys 不包含 key,抛出一个 TypeError 异常。
    2. uncheckedResultKeys 中移除 key
  20. 如果 extensibleTargettrue,返回 trapResult
  21. 对于 targetConfigurableKeys 中的每个元素 key,执行
    1. 如果 uncheckedResultKeys 不包含 key,抛出一个 TypeError 异常。
    2. uncheckedResultKeys 中移除 key
  22. 如果 uncheckedResultKeys 非空,抛出一个 TypeError 异常。
  23. 返回 trapResult
Note

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

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

10.5.12 [[Call]] ( thisArgument, argumentsList )

The [[Call]] internal method of 一个 Proxy 异质对象 obj takes arguments thisArgument (一个 ECMAScript 语言值) and argumentsList (一个 ECMAScript 语言值列表) and returns 要么是一个正常完成,包含一个 ECMAScript 语言值,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. handlerobj.[[ProxyHandler]]
  4. 断言:handler 是一个 Object。
  5. trap 为 ? GetMethod(handler, "apply")。
  6. 如果 trapundefined,那么
    1. 返回 ? Call(target, thisArgument, argumentsList)。
  7. argArrayCreateArrayFromList(argumentsList)。
  8. 返回 ? Call(trap, handler, « target, thisArgument, argArray »)。
Note

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

10.5.13 [[Construct]] ( argumentsList, newTarget )

The [[Construct]] internal method of 一个 Proxy 异质对象 obj takes arguments argumentsList (一个 ECMAScript 语言值列表) and newTarget (一个构造器) and returns 要么是一个正常完成,包含一个 Object,要么是一个抛出完成. It performs the following steps when called:

  1. 执行 ? ValidateNonRevokedProxy(obj)。
  2. targetobj.[[ProxyTarget]]
  3. 断言:IsConstructor(target) 为 true
  4. handlerobj.[[ProxyHandler]]
  5. 断言:handler 是一个 Object。
  6. trap 为 ? GetMethod(handler, "construct")。
  7. 如果 trapundefined,那么
    1. 返回 ? Construct(target, argumentsList, newTarget)。
  8. argArrayCreateArrayFromList(argumentsList)。
  9. newObj 为 ? Call(trap, handler, « target, argArray, newTarget »)。
  10. 如果 newObj 不是一个 Object,抛出一个 TypeError 异常。
  11. 返回 newObj
Note 1

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

Note 2

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

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

10.5.14 ValidateNonRevokedProxy ( proxy )

The abstract operation ValidateNonRevokedProxy takes argument proxy (一个 Proxy 异质对象) and returns 要么是一个正常完成,包含 unused,要么是一个抛出完成. 如果 proxy 已被撤销,则它会抛出一个 TypeError 异常。 It performs the following steps when called:

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

10.5.15 ProxyCreate ( target, handler )

The abstract operation ProxyCreate takes arguments target (一个 ECMAScript 语言值) and handler (一个 ECMAScript 语言值) and returns 要么是一个正常完成,包含一个 Proxy 异质对象,要么是一个抛出完成. 它用于规定新 Proxy 对象的创建。 It performs the following steps when called:

  1. 如果 target 不是一个 Object,抛出一个 TypeError 异常。
  2. 如果 handler 不是一个 Object,抛出一个 TypeError 异常。
  3. proxyMakeBasicObject[[ProxyHandler]], [[ProxyTarget]] »)。
  4. proxy 的基本内部方法(除 [[Call]][[Construct]] 之外)设为 10.5 中规定的定义。
  5. 如果 IsCallable(target) 为 true,那么
    1. proxy.[[Call]] 设为 10.5.12 中规定的内容。
    2. 如果 IsConstructor(target) 为 true,那么
      1. proxy.[[Construct]] 设为 10.5.13 中规定的内容。
  6. proxy.[[ProxyTarget]] 设为 target
  7. proxy.[[ProxyHandler]] 设为 handler
  8. 返回 proxy