ECMAScript规范中的“新对象”与“对象”

所以,我正在看什么new ObjectObject的定义ES5规范。 出乎我的意料:

  • new Object描述了对象构造函数如何工作的整个algorithm – 处理不同types的值会发生什么。 基本上在非对象上调用ToObject – 在对象上标识,并build立在null和undefined。
  • Object有一个特殊的第一步为空和未定义的地方,它build立一个对象,然后调用对象基元上的ToObject和身份。

几次阅读说明后 – 看起来完全相同。 不过,从规格上来看,他们做了一些不同的事情 。 例如在Array – 调用new Array被指定为函数调用Array(…)等价于具有相同参数的对象创buildexpression式new Array(…)

所以 – new ObjectObject什么区别? 为什么他们有不同的指定?

为了方便 – 这是一个链接到规范 。

Object(window)永远不会克隆windownew Object(window)可能会。 所有当前的 – 可能是所有已知的 – 实现都只是返回相同的引用,尽pipe规范允许实现定义的行为。

15.2.1.1的步骤说:

  1. 如果value为null,未定义或未提供,则创build并返回一个新的Object对象,就好像使用相同的参数调用了标准的内置Object构造函数
  2. 返回ToObject(值)。

ToObject (9.9)的定义列出了一些将被第1步(表14)捕获的types,但对于Object有一个非常简单的定义:

结果是input参数(不转换)。

它明确指出input参数将按原样返回,所以它们应该是相等的引用( === )。

new Object (15.2.2.1)的定义在步骤1中有一个相似的types检查链,但new Object (1.a)的步骤是:

一世。 如果该值是本机ECMAScript对象,则不要创build新对象,而只需返回值。

II。 如果该值是主机对象,则采取操作并以取决于主机对象的实现相关方式返回结果。

也就是说,对于任何主机对象foo ,调用Object(foo)必须=== foonew Object(foo)可能=== foo

主机对象在4.3.8中定义为

对象提供的主机环境来完成ECMAScript的执行环境。

这个答案列出了一些包含windowhistory等的主机对象。通过new Object(foo)运行这些new Object(foo) 应该 (但不必)返回不同的对象。

在任何情况下,只要传递一个主机对象, new Object(foo)似乎是一个更复杂的链,按照与Object(foo)几乎相同的方式推迟ToObject

不幸的是,15.2.2.1.1.a.ii指出“结果是以实现相关的方式返回的”,并且没有关于“采取的行动”的细节,看来Chrome会返回相同的对象(相同的引用)列出所有列出的“主机对象”。

使用这个脚本来检查:

 var objects = [ /* Native objects */ 'Object', 'Date', 'Math', 'parseInt', 'eval', /* Host objects */ 'window', 'document', 'location', 'history', 'XMLHttpRequest', 'setTimeout' ]; function getDefinedReference(name) { if (eval('typeof ' + name) !== 'undefined') { return eval(name); } else { throw new Error('' + name + ' is not defined.'); } } function checkIdentity(name) { try { var ref = getDefinedReference(name); var no = new Object(ref); var o = Object(ref); console.log(name, ref === no, ref === o, no === o); if (ref === o && no !== o) { // Make sure ref === Object(ref) but not new Object(ref) console.log(name, 'returns different references.'); } } catch (e) { console.warn(e); } } objects.forEach(checkIdentity); if (typeof window !== 'undefined') { for (var f in window) { checkIdentity(f); } }