阅读(1832) (2)

属性描述符及属性标识符规范类型

2017-06-16 15:07:12 更新

属性描述符类型是用来解释命名属性的具体的操作的特性集。属性描述符类型的值是记录项,由命名字段组成,每个字段的名称是一个特性名并且它的值是一个相应的特性值,这些特性指定在 8.6.1。此外,任何字段都可能存在或不存在。

 根据是否存在或使用了某些字段,属性描述符的值可进一步划分为数据属性描述符和访问器属性描述符。一个数据属性描述符 里包括叫做 [[Value]] 或 [[Writable]] 的字段。一个访问器属性描述符里包括叫做 [[Get]] 或 [[Set]] 的字段。任何属性描述都可能有名为 [[Enumerable]] 和 [[Configurable]] 的字段。一个属性描述符不能同时是数据属性描述符和访问器属性描述符;但是,它可能二者都不是。一个通用属性描述符是,既不是数据属性描述符也不是访问器属性描述符的属性描述符值。一个完全填充属性描述符是访问器属性描述符或数据属性描述符,并且拥有 8.6.1 Table 5 或 Table 6 里定义的所有属性特性对应的字段。

 本规范中为了便于标记,使用一种类似对象字面量的语法来定义属性描述符。例如,属性描述符 {[[Value]]: 42, [[Writable]]: false, [[Configurable]]: true},就定义了一个数据属性描述符。字段名称的顺序并不重要。任何没有明确列出的字段被认为是不存在的。

 在规范中的文本和算法里,可用点符号来指明一个属性描述符的特定字段。例如,如果 D 是一个属性描述符,那么 D.[[Value]] 是“D 的 [[Value]] 字段”的简写。

 属性标识符类型用于关联属性名称与属性描述符。属性标识符类型的值是 (name, descriptor) 形式的一对值,其中 name 是一个字符串和 descriptor 是一个属性描述符值。

 在本规范中使用以下的抽象操作来操作属性描述符值:

IsAccessorDescriptor (Desc)

 当用属性描述 Desc 调用抽象操作 IsAccessorDescriptor,采用以下步骤:

  1. 如果 Desc 是 undefined,那么返回 false。
  2. 如果 Desc.[[Get]] 和 Desc.[[Set]] 都不存在,则返回 false。
  3. 返回 true。

IsDataDescriptor (Desc)

 当用属性描述 Desc 调用抽象操作 IsDataDescriptor,采用以下步骤:

  1. 如果 Desc 是 undefined,那么返回 false。
  2. 如果 Desc.[[Value]] 和 Desc.[[Writable]] 都不存在,则返回 false。
  3. 返回 true。

IsGenericDescriptor (Desc)

 当用属性描述 Desc 调用抽象操作 IsDataDescriptor,采用以下步骤:

  1. 如果 Desc 是 undefined,那么返回 false。
  2. 如果 IsAccessorDescriptor(Desc) 和 IsDataDescriptor(Desc) 都是 false, 则返回 true。
  3. 返回 false。

FromPropertyDescriptor (Desc)

 当用属性描述 Desc 调用抽象操作 FromPropertyDescriptor,采用以下步骤:

 假定以下算法的 Desc 是 [[GetOwnProperty]]( 见 8.12.1) 返回的完全填充的 属性描述。

  1. 如果 Desc 是 undefined,那么返回 false。
  2. 令 obj 为仿佛使用 new Object() 表达式创建的新对象,这里的 Object 是标准内置构造器名。
  3. 如果 IsDataDescriptor(Desc) 是 true,则用参数 "value", 属性描述符 {[[Value]]: Desc.[[Value]], [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, false 调用 obj 的 [[DefineOwnProperty]] 内部方法。用参数 "writable", 属性描述符 {[[Value]]: Desc.[[Writable]], [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, false 调用 obj 的 [[DefineOwnProperty]] 内部方法。
  4. 否则,IsAccessorDescriptor(Desc) 必定是 true,所以用参数 "get", 属性描述符 {[[Value]]: Desc.[[Get]], [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, false 调用 obj 的 [[DefineOwnProperty]] 内部方法。用参数 "set", 属性描述符 {[[Value]]: Desc.[[Set]], [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, false 调用 obj 的 [[DefineOwnProperty]] 内部方法。
  5. 用参数 "enumerable", 属性描述符 {[[Value]]: Desc.[[Enumerable]], [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, false 调用 obj 的 [[DefineOwnProperty]] 内部方法。
  6. 用参数 "configurable", 属性描述符 {[[Value]]: Desc.[[Configurable]], [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, false 调用 obj 的 [[DefineOwnProperty]] 内部方法。
  7. 返回 obj。

ToPropertyDescriptor (Obj)

 当用对象 Desc 调用抽象操作 FromPropertyDescriptor,采用以下步骤:

  1. 如果 Type(Obj) 不是 Object,抛出一个 TypeError 异常。
  2. 令 desc 为创建初始不包含字段的新属性描述的结果。
  3. 如果用参数 "enumerable" 调用 Obj 的 [[HasProperty]] 内部方法的结果是 true,则令 enum 为用参数 "enumerable" 调用 Obj 的 [[Get]] 内部方法的结果。设定 desc 的 [[Enumerable]] 字段为 ToBoolean(enum)。
  4. 如果参数 "configurable" 调用 Obj 的 [[HasProperty]] 内部方法的结果是 true,则令 conf 为用参数 "enumerable" 调用 Obj 的 [[Get]] 内部方法的结果。设定 desc 的 [[Configurable]] 字段为 ToBoolean(conf)。
  5. 如果参数 "value" 调用 Obj 的 [[HasProperty]] 内部方法的结果是 true,则令 value 为用参数 "value" 调用 Obj 的 [[Get]] 内部方法的结果。设定 desc 的 [[Value]] 字段为 value。
  6. 如果参数 "writable" 调用 Obj 的 [[HasProperty]] 内部方法的结果是 true,则令 writable 为用参数 "writable" 调用 Obj 的 [[Get]] 内部方法的结果。设定 desc 的 [[Writable]] 字段为 ToBoolean(writable)。
  7. 如果参数 "get" 调用 Obj 的 [[HasProperty]] 内部方法的结果是 true,则令 getter 为用参数 "get" 调用 Obj 的 [[Get]] 内部方法的结果。如果 IsCallable(getter) 是 false 并且 getter 不是 undefined,则抛出一个 TypeError 异常。设定 desc 的 [[Get]] 字段为 getter。
  8. 如果参数 "set" 调用 Obj 的 [[HasProperty]] 内部方法的结果是 true,则令 setter 为用参数 "set" 调用 Obj 的 [[Get]] 内部方法的结果。如果 IsCallable(setter) 是 false 并且 setter 不是 undefined,则抛出一个 TypeError 异常。设定 desc 的 [[Set]] 字段为 Setter。
  9. 如果存在 desc.[[Get]] 或 desc.[[Set]],则如果存在 desc.[[Value]] 或 desc.[[Writable]],则抛出一个 TypeError 异常。
  10. 返回 desc