Был ли способ создать объект без прототипа до ES5?

Был ли способ создать объект без прототипа до 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 ответа

Решение

Как показал @Oriol, не было "официального" (совместимого со спецификацией) способа сделать это.

Однако действительно был объект, у которого не было прототипа - Object.prototype сам.

15.2.4 Свойства объекта-прототипа объекта

Значение внутреннего [[Prototype]] Свойство объекта-прототипа объекта null и значение внутреннего [[Class]] свойство "Object",

Вы можете потенциально "создать" такой объект, создав новую среду ("царство" в терминах ES6), например, через <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
});

Нет. Searching [[Prototype]] в спецификации ES3 показано, что единственный способ изменить [[Prototype]] на произвольное заданное значение - через [[Construct]].

Тем не менее, это работает только если это значение, если объект. Если это не так (включая ноль), для [[Prototype]] будет установлено начальное значение Object.prototype,

13.2.2 [[Построить]]

Когда вызывается свойство [[Construct]] для объекта Function F, предпринимаются следующие шаги:

  1. Создайте новый собственный объект ECMAScript.
  2. Установите для свойства [[Class]] Результата (1) значение "Object",
  3. Получить значение prototype собственность Ф.
  4. Если Result(3) является объектом, установите для свойства [[Prototype]] Result(1) значение Result(3).
  5. Если Result(3) не является объектом, задайте для свойства [[Prototype]] Result(1) исходный объект-прототип Object, как описано в 15.2.3.1.
  6. Вызвать свойство [[Call]] для F, указав Result(1) в качестве значения this и предоставив список аргументов, переданный в [[Construct]] в качестве значений аргумента.
  7. Если Type(Result(6)) равен Object, вернуть Result(6).
  8. Вернуть результат (1).
Другие вопросы по тегам