2012-10-31 85 views
6

我阅读过用于ES6草案,我注意到本说明中Object.prototype.toString部分:接入[[NativeBrand]]/[[类]在ES6(ECMAScript中6)

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

从阅读this thread ES-讨论,这听起来像[[Class]]被用在ES6草案[[NativeBrand]]更换,使他们能够作为非扩展的(那些是至少Allen Wirfs-Brock's thoughts)指定。

好奇,我跑在Firefox和Chrome快速测试(试验启用JavaScript):

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

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

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


1. Chrome和Firefox的行为是否正确?

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

是否有谁一直跟着es讨论更热烈地有任何相关的信息?或者谁能​​更好地理解草稿语言?


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(无前缀"~")。

+0

回答的最后一个问题(约〜等)是有依赖于现有的网络上现有的代码OptoString结果值对于现有的ES5内置插件不具有欺骗性。我们希望保持该保证,但仅限于O.p.toString在ES <= 5中知道的对象/ [[Class]]值。 –

+0

'〜'步骤被rev 32删除。 – Knu

+0

“这让我知道如果unknownObject是一个String对象,无论它构造了什么框架。”不在Opera中。 – Knu

回答

1

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

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

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

您可以找到产生此in this thread原始讨论ES-讨论

+0

谢谢,指出我在正确的方向,并给了我需要的术语。我已经用上面更完整的答案更新了我的问题,为了后代。 –