访问ES6中的[[NativeBrand]] / [[Class]](ECMAScript 6)

时间:2012-10-31 05:14:54

标签: javascript ecmascript-harmony

我正在阅读ES6的草稿,我在Object.prototype.toString部分注意到了这个注释:

  

历史上,此函数偶尔用于访问字符串   以前使用的[[Class]]内部属性的值   本规范的版本作为各种标称类型标签   内置对象。 toString的这个定义保留了能力   将它用作那些特定类型的内置对象的可靠测试   但它没有为其他人提供可靠的类型测试机制   各种内置或程序定义的对象。

从es-discuss上阅读this thread,听起来{ES}草案中的[[Class]][[NativeBrand]]替换,以便他们可以将其指定为不可扩展(这些是至少Allen Wirfs-Brock's thoughts)。

好奇,我在FireFox和Chrome上进行了快速测试(启用了实验性JavaScript):

Object.prototype.toString.apply(new WeakMap());
=> '[object WeakMap]'

"WeakMap"不是ES6草案中指定的[[NativeBrand]]之一。但是,此测试在两个浏览器上都返回"[object WeakMap]"

所以我很困惑。我有几个问题。


1。 Chrome和Firefox的行为是否正常?

从阅读草稿的一种方式来看,它们应该返回[object Object](所有这些都是新的,所以在这些浏览器的未来版本中看到这种变化我不会感到惊讶) 。但是,我很难理解草案本节的用意,特别是因为有些地方有"???"

是否有人更热切地关注es-discuss有任何相关信息?或者更能理解草案语言的人?


2。是否有替代Object.prototype.toString

从上面引用的注释中可以看出,Object.prototype.toString因为遗留原因而被保留,就像现在应该使用的新内容一样。特别是节点中读取"it does not provide a reliable type testing mechanism for other kinds of built-in ... objects"的部分。这是否意味着未来的内置插件无法使用此方法进行测试?

让我们使用一个具体的例子。

如果我想确保从未知来源收到的对象是String对象(实际构造的String对象,而不是原始字符串),我可以这样做:

if (Object.prototype.toString.apply(unknownObject) != '[object String]')
    throw new TypeError('String object expected.');

这让我知道unknownObjectString对象,无论它构建在哪个帧中。

我的问题是,这应该是我进入ES6的方法吗?还是有替代方案吗?像Object.getNativeBrandOf

这样的东西

第3。由于[[NativeBrand]]似乎不会包含未来的对象类型,因此如何测试这些对象?

这会有用吗?

if (Object.prototype.toString.apply(unknownObject) != '[object Symbol]')
    throw new TypeError('Symbol expected.');

...假设Symbol是私人姓名的最终名称。

我应该使用它吗?

if (Object.prototype.toString.apply(unknownObject) != '[object WeakMap]')
    throw new TypeError('WeakMap expected.');

......还是其他什么?


我问的原因是我目前正在编写代码,希望能够在一两年内尽可能轻松地过渡到ES6。如果有Object.prototype.toString的替换,那么我可以将其填入并从那里继续。谢谢!


更新

benvie 的回答为我提供了正确的术语,可以搜索并理解我的问题的答案。

我发现an email from Allen Wirfs-Brock on es-discuss涉及此问题。

这是我找到的,对于其他人提出同样的问题:

1。 Chrome和Firefox的行为是否正常?

是的,为什么在下面解释。

2。是否有替代Object.prototype.toString

就像现在一样,会有一些"替代品"在可能性的意义上,但不是替换

a。 使用@@toStringTag符号。但是,我的理解是仍然可能会使用Object.prototype.toString。提供@@toStringTag是为了扩展可以从Object.prototype.toString返回的结果。如果你有一个原型,你想添加自己的字符串标记,你可以使用@@toStringTag将值设置为任何字符串。 Object.prototype.toString将返回此值,除非此值是ES5内置插件之一,在这种情况下,字符串标记将添加'〜'。

b。 在用户定义的对象上使用私有符号。我读了一封电子邮件,宣传这是对用户定义进行相同类型检查的最佳方法宾语。但是,我不知道这是如何真正解决这个问题的,因为我无法理解它是如何成为一个跨框架解决方案而且它不会让你检查ES6内置插件。

所以即使有一些替代方案,现在坚持使用Object.prototype.toString并继续前进也是一件好事,但有一点需要注意:

它确保你有一个内置的ES5,例如String,但是确保你有一个ES6内置因为它不会是万无一失的,因为他们可以被@@toStringTag欺骗。我不确定为什么会这样,我可能会遗漏某些东西,或者随着规范的发展而改变。

第3。由于[[NativeBrand]]似乎不会包含未来的对象类型,因此如何测试这些对象?

如上所述,Object.prototype.toString仍可用于ES6内置插件,但它并非万无一失,因为任何有权访问@@toStringTag符号的人都可以欺骗它。但是,也许不应该是傻瓜式方法,因为Object.prototype.toString(weakmap) == '[object WeakMap]'并不代表weakmap instanceof WeakMap(并且它不应该! )。 weakmap可能来自另一个框架,也可能是用户创建的类似弱图的对象。你真正知道的唯一一件事就是报告功能上等同于WeakMap。

似乎有一个问题,为什么你不能拥有一个用户定义的对象,该对象报告在功能上等同于StringArray(没有带前缀的"~" })。

1 个答案:

答案 0 :(得分:1)

目前这是ES6规范中的一个移动目标。对于现有的对象集,由于各种原因(包括兼容性)而维护现有的机制。在最新的ES6规范published October 26th中,您可以找到潜在未来方向的一些提示

  

15.4.6.2.4 ArrayIterator.prototype。@@ toStringTag
    @@ toStringTag属性的初始值是     字符串值“Array Iterator”。

     

15.14.5.13 Map.prototype。@@ toStringTag
    @@ toStringTag属性的初始值是字符串值“Map”。

您可以在es-discuss上找到原始讨论in this thread