Вернуться к уроку

Где в DOM-иерархии document?

важность: 4

Объектом какого класса является document?

Какое место он занимает в DOM-иерархии?

Наследует ли он Node или Element?

Воспользуйтесь для решения тем фактом, что DOM-узлы образуют стандартную прототипную иерархию классов.

Объектом какого класса является document, можно выяснить так:

alert(document); // [object HTMLDocument]

Или так:

alert(document.constructor); // function HTMLDocument() { ... }

Итак, document – объект класса HTMLDocument.

Какое место HTMLDocument занимает в иерархии?

Можно поискать в документации. Но попробуем выяснить это самостоятельно.

Вопрос не такой простой и требует хорошего понимания прототипного наследования.

Вспомним, как оно устроено:

  • Методы объекта document находятся в prototype конструктора, в данном случае – HTMLDocument.prototype.
  • У HTMLDocument.prototype есть ссылка __proto__ на прототип-родитель.
  • У прототипа-родителя может быть ссылка __proto__ на его родитель, и так далее.

При поиске свойства в document, если его там нет, оно ищется в document.__proto__, затем в document.__proto__.__proto__ и так далее, пока не найдём, или пока цепочка __proto__ не закончится. Это обычное устройство класса, без наследования.

Нам нужно лишь узнать, что находится в этих самых __proto__.

Строго говоря, там могут быть любые объекты. Вовсе не обязательно, чтобы объектам из цепочки прототипов соответствовали какие-то конструкторы.

Вполне может быть цепочка, где родители – просто обычные JS-объекты:

document -> HTMLDocument.prototype -> obj1 -> obj2 -> ...

Однако, здесь мы знаем, что наследование – «на классах», то есть, эти объекты obj1, obj2 являются prototype неких функций-конструкторов:

document -> HTMLDocument.prototype -> F1.prototype -> F2.prototype -> ...

Что стоит на месте F1, F2?

Опять же, если говорить про некие абстрактные объекты, то откуда нам знать, какие функции на них ссылаются через prototype? Ниоткуда. Один объект может быть в prototype хоть у десятка функций.

Но в стандартном прототипном наследовании один объект является prototype ровно у одной функции. Причём при создании функции в её prototype уже есть объект со свойством constructor, которое ссылается обратно на функцию:

F.prototype = { constructor: F }

Это свойство constructor, если конечно его не удалить или не перезаписать нечаянно (чего делать не следует), и позволяет из прототипа узнать соответствующий ему конструктор.

// цепочка наследования:
alert(HTMLDocument.prototype.constructor); // function HTMLDocument
alert(HTMLDocument.prototype.__proto__.constructor); // function Document
alert(HTMLDocument.prototype.__proto__.__proto__.constructor); // function Node

При выводе объекта через console.dir(document) в Google Chrome, мы тоже можем, раскрывая __proto__, увидеть эти названия (HTMLDocument, Document, Node).

Браузерная консоль их берёт как раз из свойства constructor.