javascript - 在 ES6 (ECMAScript 6) 中访问 [[NativeBrand]]/[[Class]]

标签 javascript ecmascript-harmony

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

Historically, this function was occasionally used to access the string value of the [[Class]] internal property that was used in previous editions of this specification as a nominal type tag for various built-in objects. This definition of toString preserves the ability to use it as a reliable test for those specific kinds of built-in objects but it does not provide a reliable type testing mechanism for other kinds of built-in or program defined objects.



来自阅读 this thread在 es-discuss 上,听起来像是 [[Class]]正在替换为 [[NativeBrand]]在 ES6 草案中,以便他们可以将其指定为不可扩展(那些至少是 Allen Wirfs-Brock's thoughts )。

出于好奇,我在 FireFox 和 Chrome 中运行了一个快速测试(启用了实验性 JavaScript):
Object.prototype.toString.apply(new WeakMap());
=> '[object WeakMap]'
"WeakMap"不是 [[NativeBrand]] 之一s 在 ES6 草案中指定。但是,此测试返回 "[object WeakMap]"在两种浏览器上。

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

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

从阅读草稿的一种方式来看,听起来他们应该返回 [object Object] (而且所有这些都是非常新的,所以在这些浏览器的 future 版本中看到这种变化我不会感到惊讶)。但是,我很难理解这部分草案的意图,尤其是有些地方带有"???" .

有没有更热心关注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"的节点部分.这是否意味着无法使用此方法测试 future 的内置插件?

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

如果我想确保从未知来源收到的对象是 String对象(实际构造的 String 对象,不是原始字符串),我可以这样做:
if (Object.prototype.toString.apply(unknownObject) != '[object String]')
    throw new TypeError('String object expected.');

这让我知道 unknownObjectString对象,无论它是在什么框架中构建的。

我的问题是,这应该是我向 ES6 迈进的方法吗?或者有其他选择吗?类似 Object.getNativeBrandOf ?

3. 自 [[NativeBrand]]似乎它不会包括 future 类型的对象,如何测试这些对象?

这会起作用吗?
if (Object.prototype.toString.apply(unknownObject) != '[object Symbol]')
    throw new TypeError('Symbol expected.');

...假设 Symbol是私有(private)名称的最终名称。

我应该使用这个吗?
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 ?

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

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

在用户定义的对象上使用私有(private)符号。我读过一封电子邮件,宣传这是对用户定义的对象进行相同类型检查的最佳方式。但是,我不明白这如何真正解决问题,因为我无法理解它如何成为跨框架解决方案,并且它不允许您检查 ES6 内置程序。

因此,即使有一些替代方案,最好还是坚持使用 Object.prototype.toString现在和 future ,有一个警告:

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

3. 自 [[NativeBrand]]似乎它不会包括 future 类型的对象,如何测试这些对象?

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

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

最佳答案

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

15.4.6.2.4 ArrayIterator.prototype.@@toStringTag
The initial value of the @@toStringTag property is the string value "Array Iterator".

15.14.5.13 Map.prototype.@@toStringTag
The initial value of the @@toStringTag property is the string value "Map".



您可以找到起源于此 in this thread 的原始讨论在 es-discus 上

关于javascript - 在 ES6 (ECMAScript 6) 中访问 [[NativeBrand]]/[[Class]],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13151643/

相关文章:

node.js - Openshift 上的和谐

javascript - 使用 JavaScript ES6 模块导入现有库

javascript - 为什么我无法从命令行通过 "node --harmony test.js"启动和谐模式?

javascript - 在我的例子中如何仅发送一次 AJAX 调用

javascript - 带有 HTML 标签的字符串在 foreach 中无法被识别

javascript - ReactJS 循环执行Action

javascript - 不知道我做错了什么 - 获取不是函数错误

javascript - 是否可以在 ecmascript-harmony 中找到对象的类和模块

javascript - 其他人可以在他们的 Node.js REPL 中使用 let 语句吗?

javascript - Parse - JavaScript 指针查询,从指针返回解析对象的问题