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

时间:2016-03-20 17:39:15

标签: javascript ecmascript-3

有没有办法在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。我在这里用它来说明。

2 个答案:

答案 0 :(得分:2)

没有。在ES3 spec中搜索[[Prototype]]表示将[[Prototype]]更改为任意给定值的唯一方法是通过[[Construct]]。

但是,只有当一个对象的值时,它才有效。如果不是(包括null),[[Prototype]]将被设置为Object.prototype的初始值。

  

13.2.2 [[Construct]]

     

当调用Function对象F的[[Construct]]属性时,   采取以下步骤:

     
      
  1. 创建一个新的本机ECMAScript对象。
  2.   
  3. 将Result(1)的[[Class]]属性设置为"Object"
  4.   
  5. 获取F。
  6. prototype属性的值   
  7. 如果Result(3)是对象,请将Result(1)的[[Prototype]]属性设置为Result(3)。
  8.   
  9. 如果Result(3)不是对象,请将Result(1)的[[Prototype]]属性设置为原始Object原型对象,如   15.2.3.1。
  10.   
  11. 调用F的[[Call]]属性,提供Result(1)作为 this 值,并提供传递给[[Construct]]的参数列表作为参数值。
  12.   
  13. 如果Type(Result(6))是Object,则返回Result(6)。
  14.   
  15. 返回结果(1)。
  16.   

答案 1 :(得分:2)

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

然而,确实存在一个没有原型的对象 - Object.prototype本身。

  

15.2.4对象原型对象的属性

     

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

您可以通过实例化新环境(ES6术语中的“领域”)来“创建”此类对象,例如:通过<iframe>,抓住它的Object.prototype,剥去它的属性并vo-你有一个新的空物体。

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
});