Объектом какого класса является `document`, можно выяснить так:
```js
//+ run
alert(document); // [object HTMLDocument]
```
Или так:
```js
//+ run
alert(document.constructor); // function HTMLDocument() { ... }
```
Итак, `document` -- объект класса `HTMLDocument`.
Какое место `HTMLDocument` занимает в иерархии?
Можно поискать в документации. Но попробуем выяснить это самостоятельно.
Вопрос не такой простой и требует хорошего понимания [прототипного наследования](/class-inheritance).
Вспомним, как оно устроено:
- Методы объекта `document` находятся в `prototype` конструктора, в данном случае -- `HTMLDocument.prototype`.
- У `HTMLDocument.prototype` есть ссылка `__proto__` на прототип-родитель.
- У прототипа-родителя может быть ссылка `__proto__` на его родитель, и так далее.
При поиске свойства в `document`, если его там нет, оно ищется в `document.__proto__`, затем в `document.__proto__.__proto__` и так далее, пока не найдём, или пока цепочка `__proto__` не закончится. Это обычное устройство класса, без наследования.
Нам нужно лишь узнать, что находится в этих самых `__proto__`.
Строго говоря, там могут быть любые объекты. Вовсе не обязательно, чтобы объектам из цепочки прототипов соответствовали какие-то конструкторы.
Вполне может быть цепочка, где родители -- просто обычные JS-объекты:
```js
document -> HTMLDocument.prototype -> obj1 -> obj2 -> ...
```
Однако, здесь мы знаем, что наследование -- "на классах", то есть, эти объекты `obj1`, `obj2` являются `prototype` неких функций-конструкторов:
```js
document -> HTMLDocument.prototype -> F1.prototype -> F2.prototype -> ...
```
Что стоит на месте `F1`, `F2`?
Опять же, если говорить про некие абстрактные объекты, то откуда нам знать, какие функции на них ссылаются через `prototype`? Ниоткуда. Один объект может быть в `prototype` хоть у десятка функций.
Но в стандартном прототипном наследовании один объект является `prototype` ровно у одной функции. Причём при создании функции в её `prototype` уже есть объект со свойством `constructor`, которое ссылается обратно на функцию:
```js
F.prototype = { constructor: F }
```
Это свойство `constructor`, если конечно его не удалить или не перезаписать нечаянно (чего делать не следует), и позволяет из прототипа узнать соответствующий ему конструктор.
```js
//+ run
// цепочка наследования:
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`.