ECMAScript规范中的“新对象”与“对象”
所以,我正在看什么new Object
和Object
的定义ES5规范。 出乎我的意料:
-
new Object
描述了对象构造函数如何工作的整个algorithm – 处理不同types的值会发生什么。 基本上在非对象上调用ToObject
– 在对象上标识,并build立在null和undefined。 -
Object
有一个特殊的第一步为空和未定义的地方,它build立一个对象,然后调用对象基元上的ToObject
和身份。
几次阅读说明后 – 看起来完全相同。 不过,从规格上来看,他们做了一些不同的事情 。 例如在Array
– 调用new Array
被指定为函数调用Array(…)
等价于具有相同参数的对象创buildexpression式new Array(…)
。
所以 – new Object
和Object
什么区别? 为什么他们有不同的指定?
为了方便 – 这是一个链接到规范 。
Object(window)
永远不会克隆window
但new Object(window)
可能会。 所有当前的 – 可能是所有已知的 – 实现都只是返回相同的引用,尽pipe规范允许实现定义的行为。
15.2.1.1的步骤说:
- 如果value为null,未定义或未提供,则创build并返回一个新的Object对象,就好像使用相同的参数调用了标准的内置Object构造函数
- 返回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)
必须=== foo
但new Object(foo)
可能=== foo
。
主机对象在4.3.8中定义为
对象提供的主机环境来完成ECMAScript的执行环境。
这个答案列出了一些包含window
, history
等的主机对象。通过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); } }