ECMAScript规范中的`new Object` vs`Object`

时间:2015-06-12 11:03:16

标签: javascript language-lawyer ecmascript-5

因此,我在new ObjectObject的定义中查看ES5规范。令我惊讶的是:

  • new Object描述了对象构造函数如何工作的整个算法 - 处理不同类型的值所发生的事情。基本上在非对象上调用ToObject - 对象上的标识和构建为null和undefined。
  • Object有一个特殊的第一步,用于null和undefined,它构建一个对象,然后在对象的原语和标识上调用ToObject

几次阅读说明后 - 他们似乎相同。但是,从规范中可以清楚地看出它们某些是不同的。例如,在Array中,调用new Array被指定为 the function call Array(…) is equivalent to the object creation expression new Array(…) with the same arguments.`

所以 - new ObjectObject之间有什么区别?他们为什么以不同的方式指定?

为方便起见 - 这是一个link to the spec

1 个答案:

答案 0 :(得分:16)

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

15.2.1.1的步骤说:

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

ToObject(9.9)的定义列出了将在步骤1(表14)中捕获的几种类型,但Object的定义非常简单:

  

结果是输入参数(无转换)。

它明确声明输入参数将按原样返回,因此它们应该是相等的引用(===)。

new Object(15.2.2.1)的定义在步骤1中具有类似的类型检查链,但对象(1.a)的步骤是:

  

我。如果值是本机ECMAScript对象,则不要创建新对象,只需返回值。

     

II。如果该值是宿主对象,则执行操作并以依赖于实现的方式返回结果,该方式可能取决于宿主对象。

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

主机对象在4.3.8中定义为

  

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

This answer列出了一些要包含windowhistory等的主机对象。通过new Object(foo) 运行这些对象(但不是必须)返回一个不同的对象。

在任何情况下传递一个主机对象,new Object(foo)似乎是一个更复杂的链,与ToObject的方式大致相同Object(foo)

不幸的是,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);
  }
}
                                                                         

找不到Objectnew Object行为不同的任何对象。 @ Xotic750似乎是正确的,它可以依赖于实现,但没有人使用它。