1

在 ES5 之前有没有办法在没有原型的情况下创建对象?

即类似Object.create(null)(ES5)

我认为这样的事情可能会奏效,但最终语句意外返回true

function withPrototype(p) {
  function temp(){}
  temp.prototype = p;
  return new temp();
}

Object.getPrototypeOf(withPrototype(null)) === Object.prototype; // true

Object.getPrototypeOf是ES5。我在这里用它来展示。

4

2 回答 2

2

[[Prototype]]不。在ES3 规范中搜索表明,将 [[Prototype]] 更改为任意给定值的唯一方法是通过 [[Construct]]。

但是,它仅在该值是对象时才有效。如果不是(包括null),则 [[Prototype]] 将设置为 的初始值Object.prototype

13.2.2 [[构造]]

调用 Function 对象 F 的 [[Construct]] 属性时,将执行以下步骤:

  1. 创建一个新的原生 ECMAScript 对象。
  2. 将 Result(1) 的 [[Class]] 属性设置为"Object"
  3. 获取prototypeF 的属性值。
  4. 如果 Result(3) 是一个对象,则将 Result(1) 的 [[Prototype]] 属性设置为 Result(3)。
  5. 如果 Result(3) 不是对象,则将 Result(1) 的 [[Prototype]] 属性设置为原始 Object 原型对象,如 15.2.3.1 中所述。
  6. 调用 F 的 [[Call]] 属性,提供 Result(1) 作为this值,并提供传递给 [[Construct]] 的参数列表作为参数值。
  7. 如果 Type(Result(6)) 是 Object,则返回 Result(6)。
  8. 返回结果(1)。
于 2016-03-20T18:37:33.047 回答
2

正如@Oriol 所示,没有“官方”(符合规范)的方式来做到这一点。

然而,确实有一个没有原型的物体——Object.prototype它本身。

15.2.4 对象原型对象的属性

[[Prototype]]Object 原型对象的内部属性null值为 ,内部[[Class]]属性值为"Object"

您可以通过实例化一个新环境(ES6 术语中的“领域”)来潜在地“创建”这样的对象,例如通过 an <iframe>,捕获它的Object.prototype,剥离它的属性,瞧——你得到了一个新的空对象。

function getNoProtoObject(callback) {
  var iframe = document.createElement('iframe');
  iframe.onload = function() {
    var obj = iframe.contentWindow.Object.prototype;
    document.body.removeChild(iframe);

    // Remove all built-in enumerable properties.
    for (var name in obj) {
      delete obj[name];
    }

    // Remove known built-in non-enumerable properties, which may vary.
    delete obj['constructor'];
    delete obj['hasOwnProperty'];
    delete obj['isPrototypeOf'];
    delete obj['propertyIsEnumerable'];
    delete obj['toLocaleString'];
    delete obj['toString'];
    delete obj['toSource'];
    delete obj['valueOf'];
    delete obj['watch'];
    delete obj['unwatch'];
    delete obj['__defineGetter__'];
    delete obj['__defineSetter__'];
    delete obj['__lookupGetter__'];
    delete obj['__lookupSetter__'];
    delete obj['__proto__'];

    callback(obj);
  };
  iframe.src = 'about:blank';
  iframe.style.display = 'none';
  document.body.appendChild(iframe);
}

getNoProtoObject(function(o) {
  console.log(o);                        // Object {  }
  console.log(Object.getPrototypeOf(o)); // null
  console.log(o.__proto__);              // undefined
});
于 2016-03-20T18:41:26.480 回答