Был ли способ создать объект без прототипа до 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, предпринимаются следующие шаги:
- Создайте новый собственный объект ECMAScript.
- Установите для свойства [[Class]] Результата (1) значение
"Object"
,- Получить значение
prototype
собственность Ф.- Если Result(3) является объектом, установите для свойства [[Prototype]] Result(1) значение Result(3).
- Если Result(3) не является объектом, задайте для свойства [[Prototype]] Result(1) исходный объект-прототип Object, как описано в 15.2.3.1.
- Вызвать свойство [[Call]] для F, указав Result(1) в качестве значения this и предоставив список аргументов, переданный в [[Construct]] в качестве значений аргумента.
- Если Type(Result(6)) равен Object, вернуть Result(6).
- Вернуть результат (1).