ES2015中的[[class]]属性

时间:2016-07-02 12:33:41

标签: javascript ecmascript-6

我正在研究简单的克隆功能

var shallowCopy = function (value) {
  // in ES2017 we can use
  // return Object.create(Object.getPrototypeOf(value), Object.getOwnPropertyDescriptors(value));
  let propDescriptors = {};
  for (let i of Object.getOwnPropertyNames(value)) {
    propDescriptors[i] = Object.getOwnPropertyDescriptor(value, i);
  }
  return Object.create(Object.getPrototypeOf(value), propDescriptors);
};

我理解Object.prototype.toString.call(shallowCopy([]))[object Object]而非[object Array]的此行为。

但是ES6中的一些新类型看起来不错

Object.prototype.toString.call(shallowCopy(new Set())) // [object Set]
Object.prototype.toString.call(shallowCopy(new Map())) // [object Map]

有人可以告诉我为什么这些物体的行为不同吗? 这种行为将来会改变吗?

谢谢。

3 个答案:

答案 0 :(得分:1)

您演示的行为与对象的[[Class]]无关。

如果您记录Map.prototype,您会发现这些新类型有toStringTag Symbol

> Map.prototype
Map {Symbol(Symbol.toStringTag): "Map"}

此Symbol属性的值用于生成toString()生成的字符串。见Symbol.toStringTag on MDN

  

用于对象的默认描述的字符串值。由Object.prototype.toString()使用。

我怀疑为了向后兼容性,这种行为会因ES6之前的类型而改变。

答案 1 :(得分:0)

该对象不是一组。真实集具有内部[[SetData]]插槽,您无法复制。

shallowCopy(new Set()).add(123); // TypeError: add method called on incompatible Object

基本上,不要相信[[Class]]知道你拥有哪种对象。嗯,实际上[[Class]]已经在ES6中被核化并且不再存在。

答案 2 :(得分:0)

规范定义了在构造名为@@toStringTag的对象的字符串表示期间使用的特殊符号。请参阅Well-Known Symbols部分,特别是将 @@ toStringTag 描述为

  

字符串值属性,用于创建对象的默认字符串描述。通过内置方法Object.prototype.toString访问。

现在,如果您为这些类型检查 @@ toStringTag 的值,例如Set

23.2.3.12 Set.prototype [@@ toStringTag]

  

@@ toStringTag属性的初始值是字符串值“Set”

随意检查其他类型,如Promise(25.4.5.4),ArrayBuffer(24.1.4.4)等。