Object.prototype
Cсылки в цепочке [[Prototype]]
используются одна за другой, когда вы тем или иным способом пытаетесь найти свойство. Поиск заканчивается при нахождении свойства или достижении конца цепочки. Но где именно "заканчивается" цепочка [[Prototype]]
?
В конце каждой типичной цепочки [[Prototype]]
находится встроенный объект Object.prototype
. Этот объект содержит различные утилиты, используемые в JS повсеместно, поскольку все обычные (встроенные, не связанные с конкретной средой исполнения) объекты в JavaScript "происходят от" объекта Object.prototype
(иными словами, имеют его на вершине своей цепочки[[Prototype]]
).
Все объекты, созданные с помощью литералов объектов, имеют один и тот же объект-прототип, на который в программе JavaScript можно сослаться так: Object.prototype
.
Объекты, созданные с помощью ключевого слова new
и вызова конструктора, в качестве прототипа получают значение свойства prototype
функции-конструктора. Поэтому объект, созданный выражением new Object()
, наследует свойства объекта Object.prototype
, как если бы он был создан с помощью литерала в фигурных скобках {}
.
Аналогично прототипом объекта, созданного выражением new Array()
, является Array.prototype
, а прототипом объекта, созданного выражением new Date()
, является Date.prototype
.
Object.prototype
– один из немногих объектов, которые не имеют прототипа: у него нет унаследованных свойств. Другие объекты-прототипы являются самыми обычными объектами, имеющими собственные прототипы. Все встроенные конструкторы (и большинство пользовательских конструкторов) наследуют прототип Object.prototype
. Например, Date.prototype
наследует свойства от Object.prototype
, поэтому объект Date, созданный выражением new Date()
, наследует свойства от обоих прототипов, Date.prototype
и Object.prototype
. Такая связанная последовательность объектов-прототипов называется цепочкой прототипов.
Повтор / пример / проверка
Начнём мы с того, что создадим пустой объект и выведем его.
var obj = {};
alert(obj); // "[object Object]" ?
Где код, который генерирует строковое представление дляalert(obj)
? Объект-то ведь пустой. Конечно же, это сделал методtoString
, который находится… Конечно, не в самом объекте (он пуст), а в его прототипеobj.__proto__
, можно его даже вывести:
alert({}.__proto__.toString); // function toString
Откуда новый объектobj
получает такой__proto__
?
- Запись
obj = {}
является краткой формойobj = new Object
, гдеObject
– встроенная функция-конструктор для объектов. - При выполнении
new Object
, создаваемому объекту ставится__proto__
поprototype
конструктора, который в данном случае равен встроенномуObject.prototype
. - В дальнейшем при обращении к
obj.toString()
– функция будет взята изObject.prototype
.
Это можно легко проверить:
var obj = {}; // метод берётся из прототипа?
alert(obj.toString == Object.prototype.toString); // true, да
// проверим, правда ли что __proto__ это Object.prototype?
alert(obj.__proto__ == Object.prototype); // true
// А есть ли __proto__ у Object.prototype?
alert(obj.__proto__.__proto__): // null, нет
ОбъектObject.prototype
– вершина иерархии, единственный, у которого__proto__
равноnull
.
Поэтому говорят, что "все объекты наследуют отObject
", а если более точно, то отObject.prototype
.