en.javascript.info/2-ui/1-document/7-basic-dom-node-properties/4-where-document-in-hierarchy/solution.md
2015-04-01 19:08:41 +03:00

4.1 KiB
Raw Blame History

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

//+ run
alert(document); // [object HTMLDocument]

Или так:

//+ run
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, если конечно его не удалить или не перезаписать нечаянно (чего делать не следует), и позволяет из прототипа узнать соответствующий ему конструктор.

//+ 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.