Was there a way to create an object without a prototype prior to ES5?

孤街醉人 提交于 2019-12-06 15:47:39
Bergi

As @Oriol has shown, there was no "official" (spec-compliant) way to do this.

However, there was indeed an object that had no prototype - Object.prototype itself.

15.2.4 Properties of the Object Prototype Object

The value of the internal [[Prototype]] property of the Object prototype object is null and the value of the internal [[Class]] property is "Object".

You could potentially "create" such an object by instantiating a new environment ("realm" in ES6 terms), e.g. via an <iframe>, capturing its Object.prototype, stripping it of its properties and voilá - you've got a new empty object.

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

No. Searching [[Prototype]] in the ES3 spec shows that the only way of changing [[Prototype]] to an arbitrary given value is through [[Construct]].

However, it only works if that value if an object. If it's not (including null), the [[Prototype]] will be set to the initial value of Object.prototype.

13.2.2 [[Construct]]

When the [[Construct]] property for a Function object F is called, the following steps are taken:

  1. Create a new native ECMAScript object.
  2. Set the [[Class]] property of Result(1) to "Object".
  3. Get the value of the prototype property of the F.
  4. If Result(3) is an object, set the [[Prototype]] property of Result(1) to Result(3).
  5. If Result(3) is not an object, set the [[Prototype]] property of Result(1) to the original Object prototype object as described in 15.2.3.1.
  6. Invoke the [[Call]] property of F, providing Result(1) as the this value and providing the argument list passed into [[Construct]] as the argument values.
  7. If Type(Result(6)) is Object then return Result(6).
  8. Return Result(1).
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!