Spec-Zone.ru › JavaScript

Object.setPrototypeOf()

Baseline Широко доступен

Эта функция хорошо зарекомендовала себя и работает на многих устройствах и версиях браузеров. Она доступна в браузерах с июля 2015 года.

Статический метод Object.setPrototypeOf() устанавливает прототип (то есть внутреннее свойство [[Prototype]]) указанного объекта другим объектом или null.

Внимание: Изменение [[Prototype]] объекта, в силу того, как современные движки JavaScript оптимизируют доступ к свойствам, в настоящее время является очень медленной операцией во всех браузерах и движках JavaScript. Кроме того, последствия изменения наследования являются тонкими и далеко идущими, и не ограничиваются временем, затраченным на оператор Object.setPrototypeOf(...), но могут распространяться на любой код, который имеет доступ к любому объекту, чей [[Prototype]] был изменен. Вы можете узнать больше в JavaScript engine fundamentals: optimizing prototypes.

Поскольку эта функция является частью языка, разработчики движков по-прежнему обязаны реализовать эту функцию производительно (в идеале). Пока разработчики движков не решат эту проблему, если вы обеспокоены производительностью, вам следует избегать установки [[Prototype]] объекта. Вместо этого создайте новый объект с желаемым [[Prototype]], используя Object.create().

Попробуйте

const obj = {};
const parent = { foo: "bar" };

console.log(obj.foo);
// Expected output: undefined

Object.setPrototypeOf(obj, parent);

console.log(obj.foo);
// Expected output: "bar"

Синтаксис

Object.setPrototypeOf(obj, prototype)

Параметры

obj
Объект, прототип которого нужно установить.
prototype
Новый прототип объекта (объект или null).

Возвращаемое значение

Указанный объект.

Исключения

TypeError
Выбрасывается в одном из следующих случаев:
  • Параметр obj является undefined или null.
  • Параметр obj является нерасширяемым, или это экзотический объект с неизменяемым прототипом, такой как Object.prototype или window. Однако ошибка не выбрасывается, если новый прототип совпадает с исходным прототипом obj.
  • Параметр prototype не является объектом или null.

Описание

Object.setPrototypeOf() обычно считается правильным способом установки прототипа объекта. Вы всегда должны использовать его вместо устаревшего доступатора Object.prototype.__proto__.

Если параметр obj не является объектом (например, число, строка и т.д.), этот метод ничего не делает — не преобразуя его в объект и не пытаясь установить его прототип — и напрямую возвращает obj как примитивное значение. Если prototype совпадает с прототипом obj, то obj возвращается напрямую, не вызывая TypeError, даже когда obj имеет неизменяемый прототип.

Из соображений безопасности некоторые встроенные объекты имеют неизменяемый прототип. Это предотвращает атаки загрязнения прототипа, особенно связанные с прокси. Ядро языка определяет только Object.prototype как экзотический объект с неизменяемым прототипом, чей прототип всегда является null. В браузерах window и location являются двумя другими очень распространенными примерами.

Object.isExtensible(Object.prototype); // true; you can add more properties
Object.setPrototypeOf(Object.prototype, {}); // TypeError: Immutable prototype object '#<Object>' cannot have their prototype set
Object.setPrototypeOf(Object.prototype, null); // No error; the prototype of `Object.prototype` is already `null`

Примеры

Псевдоклассовое наследование с использованием Object.setPrototypeOf()

Наследование в JS с использованием классов.

class Human {}
class SuperHero extends Human {}

const superMan = new SuperHero();

Однако, если мы хотим реализовать подклассы без использования class, мы можем сделать следующее:

function Human(name, level) {
  this.name = name;
  this.level = level;
}

function SuperHero(name, level) {
  Human.call(this, name, level);
}

Object.setPrototypeOf(SuperHero.prototype, Human.prototype);

// Set the `[[Prototype]]` of `SuperHero.prototype`
// to `Human.prototype`
// To set the prototypal inheritance chain

Human.prototype.speak = function () {
  return `${this.name} says hello.`;
};

SuperHero.prototype.fly = function () {
  return `${this.name} is flying.`;
};

const superMan = new SuperHero("Clark Kent", 1);

console.log(superMan.fly());
console.log(superMan.speak());

Сходство между классическим наследованием (с классами) и псевдоклассовым наследованием (с свойством prototype конструкторов), как показано выше, упоминается в Цепочки наследования.

Поскольку свойство prototype конструкторов функций доступно для записи, вы можете переназначить его новому объекту, созданному с помощью Object.create(), чтобы достичь той же цепочки наследования. Есть нюансы, на которые стоит обратить внимание при использовании create(), например, не забыть добавить свойство constructor.

В приведенном ниже примере, который также использует классы, SuperHero наследуется от Human без использования extends, вместо этого используя setPrototypeOf().

Внимание: Не рекомендуется использовать setPrototypeOf() вместо extends из-за соображений производительности и читаемости.

class Human {}
class SuperHero {}

// Set the instance properties
Object.setPrototypeOf(SuperHero.prototype, Human.prototype);

// Hook up the static properties
Object.setPrototypeOf(SuperHero, Human);

const superMan = new SuperHero();

Подклассы без extends упоминаются в ES-6 subclassing.

Спецификации

Спецификация
ECMAScript® 2027 Language Specification
# sec-object.setprototypeof

Совместимость с браузерами

Desktop Mobile Server
Chrome Edge Firefox Opera Safari Chrome Android Firefox for Android Opera Android Safari on iOS Samsung Internet WebView Android WebView on iOS Bun Deno Node.js
setPrototypeOf
34
12
31
21
9
34
31
21
9
2.0
37
9
1.0.0
1.0
0.12.0

См. также

  • Polyfill of Object.setPrototypeOf in core-js
  • Reflect.setPrototypeOf()
  • Object.prototype.isPrototypeOf()
  • Object.getPrototypeOf()
  • Object.prototype.__proto__
  • Цепочка наследования
  • ES6 In Depth: Subclassing on hacks.mozilla.org (2015)

© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API