繁体   English   中英

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

[英]Access [[NativeBrand]] / [[Class]] in ES6 (ECMAScript 6)

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

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

通过在es-discuss上阅读这个帖子 ,听起来像[[Class]]在ES6草案中被[[NativeBrand]]替换,这样他们就可以将它指定为不可扩展的(至少是Allen Wirfs-Brock的想法 )。

好奇,我在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

从上面引用的注释中可以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.');

这让我知道,如果unknownObject是一个String对象,无论它构造在什么框架中。

我的问题是,这应该是我采用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的替代Object.prototype.toString ,那么我可以将其Object.prototype.toString并从那里继续。 谢谢!


更新

benvie的回答为我提供了正确的术语来搜索和理解我的问题的答案。

我发现了Allen Wirfs-Brock关于这个问题的es-discuss的电子邮件

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

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

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

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

就像现在一样,在可能性的意义上会有一些“替代品”,但在替代品意义上却没有。

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

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

因此,即使有一些替代方案,最好现在坚持使用Object.prototype.toString并继续前进,但需要注意一点:

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

3.由于[[NativeBrand]]似乎不包含将来的对象类型,如何测试这些对象?

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

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

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

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

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

您可以在es-discuss上找到源于此主题的原始讨论

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM