From 074785cea106179cb3305637055ab0a009ca74f2 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:42:52 -0500 Subject: initial commit --- .../global_objects/object/proto/index.html | 151 +++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 files/ru/web/javascript/reference/global_objects/object/proto/index.html (limited to 'files/ru/web/javascript/reference/global_objects/object/proto') diff --git a/files/ru/web/javascript/reference/global_objects/object/proto/index.html b/files/ru/web/javascript/reference/global_objects/object/proto/index.html new file mode 100644 index 0000000000..3ee717a370 --- /dev/null +++ b/files/ru/web/javascript/reference/global_objects/object/proto/index.html @@ -0,0 +1,151 @@ +--- +title: Object.prototype.__proto__ +slug: Web/JavaScript/Reference/Global_Objects/Object/proto +tags: + - JavaScript + - Object + - Property + - Prototype + - Reference + - Référence(2) +translation_of: Web/JavaScript/Reference/Global_Objects/Object/proto +--- +
{{JSRef("Global_Objects", "Object")}}
+ +
+

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

+
+ +
+

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

+
+ +

Сводка

+ +

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

+ +

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

+ +

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

+ +

Синтаксис

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

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

+ +

Описание

+ +

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

+ +

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

+ +

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

+ +

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

+ +
var noProto = Object.create(null);
+
+console.log(typeof noProto.__proto__); // undefined
+console.log(Object.getPrototypeOf(noProto)); // null
+
+noProto.__proto__ = 17;
+
+console.log(noProto.__proto__); // 17
+console.log(Object.getPrototypeOf(noProto)); // null
+
+var protoHidden = {};
+Object.defineProperty(protoHidden, '__proto__',
+                      { value: 42, writable: true, configurable: true, enumerable: true });
+
+console.log(protoHidden.__proto__); // 42
+console.log(Object.getPrototypeOf(protoHidden) === Object.prototype); // true
+
+ +

Примеры

+ +

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

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

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

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

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

+ +

Однако, это применяется только к {{jsxref("Object.isExtensible()", "расширяемым", "", 1)}} объектам, у нерасширяемых объектов свойство __proto__ не может быть изменено:

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

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

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

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

+ +

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

+ + + + + + + + + + + + + + +
СпецификацияСтатусКомментарии
{{SpecName('ES6', '#sec-additional-properties-of-the-object.prototype-object', 'Object.prototype.__proto__')}}{{Spec2('ES6')}}Включён в (нормативное) приложение для дополнительных возможностей ECMAScript для веб-браузеров (обратите внимание, что спецификация закрепляет то, что уже реализовано).
+ +

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

+ +
+

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

+
+ +
{{Compat("javascript.builtins.Object.proto")}}
+ +

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

+ + -- cgit v1.2.3-54-g00ecf