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

`new Object` vs `Object` in the ECMAScript spec

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

阅读描述几次后 - 它们看起来相同。但是,从规范中可以清楚地看出它们有些地方 不同。例如在 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

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

15.2.1.1 的步骤说:

  1. If value is null, undefined or not supplied, create and return a new Object object exactly as if the standard built-in Object constructor had been called with the same arguments
  2. Return ToObject(value).

ToObject (9.9) 的定义列出了一些将被步骤 1 捕获的类型(在 table 14),但对于 Object 有一个非常简单的定义:

The result is the input argument (no conversion).

它明确指出输入参数将按原样 return 编辑,因此它们应该是相等的引用 (===)。

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

i. If the value is a native ECMAScript object, do not create a new object but simply return value.

ii. If the value is a host object, then actions are taken and a result is returned in an implementation-dependent manner that may depend on the host object.

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

宿主对象在 4.3.8 中定义为

object supplied by the host environment to complete the execution environment of ECMAScript.

This answer 列出了一些宿主对象以包括 windowhistory 等。运行 那些通过 new Object(foo) 应该(但不一定)return 一个不同的对象。

在任何情况下 但是 传递一个宿主对象,new Object(foo) 似乎是一个更复杂的链,它遵循 ToObject 的方式与Object(foo).

不幸的是,15.2.2.1.1.a.ii 指出“结果是 return 以依赖于实现的方式编辑的”并且没有关于“[那些] 的操作”的具体信息taken”,看起来 Chrome 将 return 相同的对象(相同的引用)用于所有列出的“宿主对象”。

使用此脚本检查:

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 似乎是正确的,它可以依赖于实现,但没有人使用它。