Внутренние и внешние окна

{{ draft() }}

В этой статье мы попытаемся объяснить понятия внутренних и внешних окон.

Считайте, что когда пользователь смотрит на документ в окне браузера, может измениться не только документ, который пользователь просматривает в данный момент, но и его содержимое. Затем добавьте к этому понятие рамки, в которых документ в окне может сам содержать другие документы, которые, в свою очередь, могут содержать больше документов.

Для того чтобы представить эти уровни сложности, необходимо рассмотреть два "типа" окон. Технически они относятся не к окнам в том виде, в каком их видит пользователь, а скорее к тому, на что он смотрит.

Окна и bfcache

Внешнее окно (outer window) - это контекст просмотра, т.е. фактическое окружение, в котором пользователю представляется {{ domxref("Document") }}. Это может быть окно или вкладка, или это может быть {{ HTMLElement("iframe") }}, содержащаяся в другом документе. HTML5 ссылается на внешнее окно как на WindowProxy.

Внутреннее окно (inner window) редставляет реальное отображаемое содержимое; это текущий вид того, что пользователь видит.

Рассмотрим этот вид окна и историю браузера:

window-strip.png

По мере навигации пользователя документы добавляются в обратный кэш (часто называемый bfcache). По сути, это внутренние окна. Они отображаются во внешнем окне, которое содержится в "физическом" окне браузера.

Но вот в чем трюк: внутреннее окно, по сути, претендует на внешнее окно. Если отображаемый в данный момент документ спросит "в каком я окне?", то в качестве ответа он получит внешнее окно. Это позволяет документу взаимодействовать с "физическим" окном, а внешнее окно может отслеживать все документы (внутренние окна), которые в нем содержатся. Другими словами, {{ domxref(" window") }} всегда возвращает внешнее окно.

Вложенные окна

Все становится немного сложнее, если учесть, что документы могут содержать другие документы. Это происходит, например, когда {{ domxref("document") }} содержит {{{ HTMLElement("frame") }} или {{ HTMLElement("iframe") }}. Навигация по самому внешнему документу возможна не только при нажатии на ссылку в одном из фреймов, но и при нажатии на ссылку в этом фрейме.

Это означает, что должна существовать иерархия внешних и внутренних окон. Рассмотрим документ, в котором есть три элемента {{ HTMLElement("iframe") }}. Иерархия будет выглядеть примерно так:

iframes-hierarchy.png

На этой диаграмме объекты, с которыми вы взаимодействуете непосредственно в DOM (т.е. {{ domxref("Window") }}, {{ domxref("Document") }}, и {{{ domxref("Element") }}, имеют синий цвет. Серые круги представляют собой более абстрактные внутренние и внешние окна, которые являются реальными объектами, с которыми вы не взаимодействуете напрямую при работе с DOM. Окно в верхней части диаграммы - это внешнее окно.

По мере того, как пользователь перемещается в каждом из документов в различных рамках, каждое из этих внутренних окон имеет свою собственную историю, которую можно перемещать вперед и назад, как и в предыдущей диаграмме.

Элемент {{ HTMLElement("iframe") }} содержит свойство contentWindow, которое дает нам объект внешнего окна {{ domxref("Window") }}, содержащий документ кадра. Аналогично свойству contentDocument фрейма передаёт объект {{ domxref("Document") }} внутри фрейма.

Окно, содержащее фрейм, можно получить из свойства {{ domxref("window.parent") }}.

Эта иерархия может продолжаться, если фреймы содержат дополнительные кадры.