Object.setPrototypeOf()
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
Предупреждение:
Изменение прототипа [[Prototype]]
объекта является, по самой природе оптимизации доступа к свойствам в современных движках JavaScript, очень медленной операцией, это справедливо для любого браузера и движка JavaScript. Изменение прототипов очень тонко и обширно влияет на производительность, причём это влияние не ограничивается просто временем, проведённым внутри метода Object.setPrototypeOf()
, оно может распространяться на любой код, который имеет доступ к любому объекту, чей прототип [[Prototype]]
был изменён. Если вы заботитесь о производительности, вы никогда не должны изменять прототип [[Prototype]]
объекта. Вместо этого создайте объект с нужным прототипом [[Prototype]]
, с помощью метода Object.create()
.
Сводка
Метод Object.setPrototypeOf()
устанавливает прототип (то есть, внутреннее свойство [[Prototype]]
) указанного объекта в другой объект или null
.
Синтаксис
Object.setPrototypeOf(obj, prototype);
Параметры
Описание
Выкидывает исключение TypeError
, если объект, чей прототип [[Prototype]]
является не расширяемым, согласно методу Object.isExtensible()
. Не делает ничего, если параметр prototype
не является объектом или значением null
(то есть, является числом, строкой, логическим значением или undefined
). В противном случае метод устанавливает прототип [[Prototype]]
объекта obj
в новое значение.
Примеры
var dict = Object.setPrototypeOf({}, null);
Полифил
Используя старое свойство Object.prototype.__proto__
, мы можем легко определить Object.setPrototypeOf()
, если он ещё не доступен:
if (!Object.setPrototypeOf) {
Object.prototype.setPrototypeOf = function (obj, proto) {
if (obj.__proto__) {
obj.__proto__ = proto;
return obj;
} else {
// Если нужно будет определить прототип у Object.create(null) объекта
var Fn = function () {
for (var key in obj) {
//Если в объект уже были определены некоторые свойства
Object.defineProperty(this, key, {
value: obj[key],
});
}
};
Fn.prototype = proto;
return new Fn();
}
};
}
Добавление цепочки прототипов
Сочетание метода Object.getPrototypeOf()
и свойства Object.prototype.__proto__
позволяет добавить целую цепочку прототипов к новому прототипу объекта:
/**
*** Object.appendChain(@object, @prototype)
*
* Присоединяет первый неродной прототип цепочки к новому прототипу.
* Возвращает @object (если он был примитивным значением, оно будет преобразовано в объект).
*
*** Object.appendChain(@object [, "@arg_name_1", "@arg_name_2", "@arg_name_3", "..."], "@function_body")
*** Object.appendChain(@object [, "@arg_name_1, @arg_name_2, @arg_name_3, ..."], "@function_body")
*
* Присоединяет первый не родной прототип цепочки к родному объекту Function.prototype, затем присоединяет
* new Function(["@arg"(s)], "@function_body") к этой цепочке.
* Возвращает функцию.
*
**/
Object.appendChain = function (oChain, oProto) {
if (arguments.length < 2) {
throw new TypeError("Object.appendChain - Not enough arguments");
}
if (typeof oProto === "number" || typeof oProto === "boolean") {
throw new TypeError(
"second argument to Object.appendChain must be an object or a string",
);
}
var oNewProto = oProto,
oReturn =
(o2nd =
oLast =
oChain instanceof this ? oChain : new oChain.constructor(oChain));
for (
var o1st = this.getPrototypeOf(o2nd);
o1st !== Object.prototype && o1st !== Function.prototype;
o1st = this.getPrototypeOf(o2nd)
) {
o2nd = o1st;
}
if (oProto.constructor === String) {
oNewProto = Function.prototype;
oReturn = Function.apply(null, Array.prototype.slice.call(arguments, 1));
this.setPrototypeOf(oReturn, oLast);
}
this.setPrototypeOf(o2nd, oNewProto);
return oReturn;
};
Использование
Первый пример: присоединение цепочки к прототипу
function Mammal() {
this.isMammal = "да";
}
function MammalSpecies(sMammalSpecies) {
this.species = sMammalSpecies;
}
MammalSpecies.prototype = new Mammal();
MammalSpecies.prototype.constructor = MammalSpecies;
var oCat = new MammalSpecies("Felis");
alert(oCat.isMammal); // 'да'
function Animal() {
this.breathing = "да";
}
Object.appendChain(oCat, new Animal());
alert(oCat.breathing); // 'да'
Второй пример: преобразование примитивного значения в экземпляр его конструктора и присоединение его цепочки к прототипу
function Symbol() {
this.isSymbol = "да";
}
var nPrime = 17;
alert(typeof nPrime); // 'number'
var oPrime = Object.appendChain(nPrime, new Symbol());
alert(oPrime); // '17'
alert(oPrime.isSymbol); // 'да'
alert(typeof oPrime); // 'object'
Третий пример: присоединение цепочки к объекту Function.prototype
и новой функции к этой цепочке
function Person(sName) {
this.identity = sName;
}
var george = Object.appendChain(
new Person("Георг"),
'alert("Привет, парни!!");',
);
alert(george.identity); // 'Георг'
george(); // 'Привет, парни!!'
Спецификации
Specification |
---|
ECMAScript® 2025 Language Specification # sec-object.setprototypeof |
Совместимость с браузерами
BCD tables only load in the browser