Movatterモバイル変換


[0]ホーム

URL:


  1. Веб-технологии для разработчиков
  2. JavaScript
  3. Справочник по JavaScript
  4. Стандартные встроенные объекты
  5. Object
  6. Object.prototype.__proto__

This page was translated from English by the community.Learn more and join the MDN Web Docs community.

View in EnglishAlways switch to English

Object.prototype.__proto__

Предупреждение:Изменение прототипа[[Prototype]] объекта является, по самой природе оптимизации доступа к свойствам в современных движках JavaScript, очень медленной операцией, это справедливо длялюбого браузера и движка JavaScript. Изменение прототипов очень тонко и обширно влияет на производительность, причём это влияние не ограничивается просто временем для операции присваиванияobj.__proto__ = ..., оно может распространяться налюбой код, который имеет доступ клюбому объекту, чей прототип[[Prototype]] был изменён. Если вы заботитесь о производительности, вы никогда не должны изменять прототип[[Prototype]] объекта. Вместо этого создайте объект с нужным прототипом[[Prototype]], с помощью методаObject.create().

Предупреждение:Хотя на сегодняшний момент большинство браузеров поддерживают свойствоObject.prototype.__proto__, его поведение только недавно было стандартизировано в новой спецификации ECMAScript 6. Если вам требуется поддержка браузеров до этой спецификации, рекомендуется использовать вместо него методObject.getPrototypeOf().

Сводка

Свойство__proto__ объектаObject.prototype является свойством доступа (комбинацией геттера и сеттера), которое расширяет внутренний прототип[[Prototype]] объекта (являющийся объектом илиnull), через который осуществлялся доступ.

Использование свойства__proto__ вызывает споры и многих оно разочаровало. Ранее оно никогда не включалось в спецификацию EcmaScript, но современные браузеры всё равно решили его реализовать. Сегодня свойство__proto__ стандартизировано в спецификации ECMAScript 6 и будет поддерживаться в будущем. Тем не менее, изменение прототипа[[Prototype]] объекта всё ещё остаётся медленной операцией, которую следует избегать, если вы беспокоитесь о производительности.

Свойство__proto__ также может использоваться при определении литерала объекта, устанавливая прототип[[Prototype]] объекта при его создании. Этот способ может рассматриваться как альтернатива методуObject.create(). Смотрите такжелитеральный синтаксис инициализации объекта.

Синтаксис

js
var shape = {},  circle = new Circle();// Установка прототипа объектаshape.__proto__ = circle;// Получение прототипа объектаconsole.log(shape.__proto__ === circle); // true

Обратите внимание: название свойства состоит из двух подчёркиваний, следующих за ними пяти символов «proto» и следующих за ними ещё двух подчёркиваний.

Описание

Геттер свойства__proto__ расширяет значение внутреннего прототипа[[Prototype]] объекта. Для объектов, созданных с использованием литеральной формы создания объекта, это значение равноObject.prototype. Для функций это значение равноFunction.prototype. Для объектов, созданных с использованием формыnew fun, гдеfun является одной из встроенных функций-конструкторов, предоставляемых JavaScript (Array,Boolean,Date,Number,Object,String и так далее — включая новые конструкторы, добавленные в процессе развития JavaScript), это значение равноfun.prototype. Для объектов, созданных с использованием формыnew fun, гдеfun является функцией, определённой в скрипте, это значение равно значениюfun.prototype во время вычисленияnew fun. Именно поэтому при присваиванииfun.prototype нового значения, ранее созданные экземплярыfun продолжат использовать предыдущее значение в качестве своего прототипа[[Prototype]], а последующие вызовыnew fun будут использовать вновь присвоенное значение в качестве своего прототипа[[Prototype]].

Геттер__proto__ позволяет прототипу[[Prototype]] объекта быть изменяемым. Объект должен быть расширяемым в соответствии сObject.isExtensible(): если это не так, выкидывается исключениеTypeError. Предоставляемое значение должно быть объектом илиnull. Предоставление любого другого значения ничего не даст.

Для понимания того, как прототипы используются для наследования, смотрите статью руководства«Наследование и цепочки прототипов».

Свойство__proto__ является простым свойством доступа на объектеObject.prototype — свойством, состоящим из геттера и сеттера. Свойство__proto__ будет найдено, если, в конечном итоге, его поиск пройдёт черезObject.prototype, но при доступе к нему не черезObject.prototype, оно найдено не будет. Если перед просмотромObject.prototype буден найдено какое-нибудь другое свойство__proto__, оно скроет искомое свойствоObject.prototype.

js
var noProto = Object.create(null);console.log(typeof noProto.__proto__); // undefinedconsole.log(Object.getPrototypeOf(noProto)); // nullnoProto.__proto__ = 17;console.log(noProto.__proto__); // 17console.log(Object.getPrototypeOf(noProto)); // nullvar protoHidden = {};Object.defineProperty(protoHidden, "__proto__", {  value: 42,  writable: true,  configurable: true,  enumerable: true,});console.log(protoHidden.__proto__); // 42console.log(Object.getPrototypeOf(protoHidden) === Object.prototype); // true

Примеры

В следующем примере создаётся новый экземплярEmployee, а затем проверяется, что его свойство__proto__ является тем же самым объектом, что и его конструкторprototype.

js
// Декларируем функцию, используемую как конструкторfunction Employee() {  /* инициализируем экземпляр */}// Создаём новый экземпляр Employeevar fred = new Employee();// Проверка на эквивалентностьfred.__proto__ === Employee.prototype; // true

В этот моментfred унаследован отEmployee, однако присваивание другого объекта вfred.__proto__ может изменить это:

js
function Cow() {  /* инициализируем экземпляр */}// Присваиваем __proto__ новый объектfred.__proto__ = Cow.prototype;

Теперьfred наследуется непосредственно отCow.prototype, а не отEmployee.prototype, и теряет свойства, изначально унаследованные отEmployee.prototype.

Однако, это применяется только красширяемым объектам, у нерасширяемых объектов свойство__proto__ не может быть изменено:

js
var obj = {};Object.preventExtensions(obj);obj.__proto__ = {}; // выкинет TypeError

Обратите внимание, что свойство__proto__ может быть переопределено даже у объектаObject.prototype, если новая цепочка заканчиваетсяnull:

js
var b = {};Object.prototype.__proto__ = Object.create(  null, // [[Prototype]]  {    hi: {      value: function () {        alert("hi");      },    },  },);b.hi();

Если свойство__proto__ объектаObject.prototype не установлено вnull, или в другой объект, чья цепочка прототипов, в конечном итоге, явно не заканчивается значениемnull, будет выкинуто исключениеTypeError «циклическое значение __proto__», поскольку цепочка должна заканчиватьсяnull (как это и происходит наObject.prototype при нормальных обстоятельствах).

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

Specification
ECMAScript® 2026 Language Specification
# sec-object.prototype.__proto__

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

Примечание:Спецификация ES6 требует поддержку свойства__proto__ только в браузерах и не требует его поддержку в других окружениях (хотя оно и рекомендуется в качестве обязательного). Если ваш код должен работать в не-браузерных окружениях, вместо свойства рекомендуется использовать методыObject.getPrototypeOf() иObject.setPrototypeOf().

Смотрите также

Help improve MDN

Learn how to contribute

This page was last modified on byMDN contributors.


[8]ページ先頭

©2009-2025 Movatter.jp