Объектная модель браузера (BOM)
DOM и BOM
DOM — это аббревиатура от Document Object Model, что в переводе означает объектную модель документа, и представляет собой кросс-платформенный и языконезависимый программный интерфейс, который трактует HTML, XHTML или XML документ как древовидную структуру, где каждый узел является объектом, представляющим часть документа, например, элемент, атрибут или текстовый фрагмент. DOM является стандартом, разработанным консорциумом W3C, и предоставляет разработчикам набор методов и свойств для программного доступа, изменения, добавления или удаления содержимого, структуры и стилей веб-страницы, делая статический HTML-документ динамическим и интерактивным. Дерево DOM начинается с корневого узла document, который содержит все остальные узлы, отражая вложенность тегов в исходном HTML-коде, и каждый элемент в этом дереве может быть найден с помощью методов, таких как getElementById, querySelector или querySelectorAll, а затем изменен, к нему могут быть добавлены дочерние элементы, изменены его атрибуты или стили, или удалены существующие узлы. DOM также предоставляет возможность работать с событиями, позволяя разработчику назначать обработчики на элементы, чтобы реагировать на действия пользователя, такие как клики, наведение мыши, нажатия клавиш и другие, делая веб-страницу интерактивной и отзывчивой на действия пользователя. Важно понимать, что DOM не является частью языка JavaScript, а представляет собой API, доступ к которому осуществляется через JavaScript в браузере, и каждый браузер реализует DOM согласно общим стандартам, хотя могут существовать небольшие различия в реализации и производительности между разными браузерами. DOM является основой всей современной веб-разработки, поскольку без него невозможно динамически изменять содержимое веб-страниц, создавать анимации, обрабатывать пользовательский ввод и строить сложные веб-приложения, и знание DOM является фундаментальным навыком для любого веб-разработчика.
BOM — это аббревиатура от Browser Object Model, что означает объектную модель браузера, и представляет собой набор объектов и методов, предоставляемых браузером для взаимодействия с самим браузером и его окружением, в отличие от DOM, который фокусируется на документе, BOM позволяет управлять окнами, вкладками, историей навигации, информацией о браузере и устройстве пользователя, а также выполнять другие операции, связанные с окружением выполнения. Основным объектом BOM является объект window, который представляет собой глобальный объект в браузерном JavaScript и служит корнем для всех других объектов BOM, включая document, location, history, navigator, screen и другие, причем все глобальные переменные, объявленные в коде, автоматически становятся свойствами объекта window. BOM предоставляет методы для управления окнами и вкладками, такие как window.open для открытия новых окон и window.close для их закрытия, методы для работы с диалоговыми окнами, такие как alert, confirm и prompt, методы для работы с таймерами, такие как setTimeout и setInterval, и методы для управления историей, такие как history.back и history.forward. В отличие от DOM, BOM не стандартизирован единой спецификацией, и хотя большинство его функциональности поддерживается всеми современными браузерами, могут существовать различия и расширения, специфичные для конкретных браузеров, что требует от разработчика осторожности при использовании менее распространенных BOM-функций. BOM также предоставляет информацию о браузере и устройстве через объект navigator, включая имя браузера, версию, операционную систему, язык пользователя и информацию о подключении к интернету, а также объект screen, содержащий информацию о размере экрана и его цветовой глубине. Понимание BOM является важным для создания веб-приложений, которые правильно взаимодействуют с браузером, управляют навигацией, адаптируются к возможностям устройства и обеспечивают плавный и согласованный пользовательский опыт на различных платформах.
DOM описывает документ — узлы HTML на странице (работа с HTML).
BOM (Browser Object Model) описывает окружение браузера — окно, адресная строка, история переходов, данные об устройстве, размеры viewport. Корневой объект — window; в браузере глобальные переменные и функции (alert, setTimeout) живут в его области видимости.
console.log(window === globalThis); // true в современных браузерах
Разбор:
- В этом фрагменте используется конструкция
console.log(window === globalThis); // true в современных браузерахкак точка входа сценария. - Код показывает последовательность действий: получение данных, проверка условий и выполнение целевого действия.
- Ключевые вызовы и свойства опираются на стандартные API JavaScript/браузера, поэтому шаблон легко перенести в реальный проект.
- Такой пример удобно расширять обработкой ошибок, логированием и дополнительной валидацией входных данных.
В Node.js вместо window — global / globalThis; DOM и BOM там нет.
Модель BOM: что запомнить
Окно вкладки — это графический контейнер, представляющий собой отдельную область просмотра в браузере, в которой загружен и отображается веб-документ, и которое в объектной модели браузера представлено объектом window, являющимся глобальным объектом для всего JavaScript-кода, выполняющегося в данной вкладке. Каждая вкладка или окно в браузере имеет свой собственный экземпляр объекта window, который полностью изолирован от окон других вкладок по соображениям безопасности, хотя существуют механизмы, такие как postMessage, для контролируемого обмена сообщениями между окнами одного или разных источников. Окно вкладки содержит ссылку на объект document, представляющий загруженную HTML-страницу, и через это окно разработчик может управлять содержимым страницы, обрабатывать события, выполнять сетевые запросы и взаимодействовать с пользователем, при этом все операции ограничены контекстом данной вкладки. Размеры окна вкладки, включая ширину и высоту видимой области, которые называются viewport, могут быть получены через свойства window.innerWidth и window.innerHeight, а положение окна на экране через свойства window.screenX и window.screenY, что важно для адаптивного дизайна и позиционирования всплывающих элементов. Современные браузеры также предоставляют возможность управлять вкладками программно, включая открытие новых вкладок через window.open, закрытие текущей вкладки через window.close с ограничениями безопасности, а также переключение между вкладками с использованием различных методов, при этом каждая вкладка работает в своем собственном потоке и имеет свой собственный event loop. Окно вкладки также является точкой входа для работы с другими BOM-объектами, такими как location для управления URL-адресом и навигацией, history для управления историей посещений в пределах вкладки, navigator для получения информации о браузере и системе, а также для работы с хранилищами, такими как localStorage и sessionStorage, которые также привязаны к конкретной вкладке или источнику.
BOM — API окна вкладки, не DOM-дерева страницы. Три опоры:
- Где пользователь —
location, параметры URL. - Как попал и куда может вернуться —
history. - Среда —
navigator, размеры окна, сеть (onLine, Connection API).
С этой схемой проще связать API с маршрутизацией и адаптивным UI.
Объект location
Объект location — это встроенный объект в браузерной объектной модели, доступный через window.location или просто location, который представляет текущий URL-адрес загруженного документа и предоставляет мощный интерфейс для получения информации о различных компонентах этого адреса, а также для управления навигацией и перенаправлениями. Объект location разбивает URL-адрес на составные части, предоставляя доступ к свойствам, таким как href для полного URL-адреса, protocol для протокола, например, http или https, host для имени хоста с портом, hostname для имени хоста без порта, port для порта, pathname для пути к ресурсу, search для строки запроса, включая вопросительный знак, и hash для фрагмента идентификатора, включая символ решетки, что позволяет разработчику анализировать и манипулировать различными частями адреса без необходимости писать сложные парсеры. Объект location также предоставляет методы для управления навигацией, включая assign, который загружает новый документ по указанному URL-адресу, сохраняя запись в истории браузера, replace, который заменяет текущий документ новым, не добавляя запись в историю, что полезно для страниц перенаправления, и reload, который перезагружает текущий документ, с возможностью принудительной загрузки с сервера. Изменение свойств объекта location, таких как href, pathname или search, автоматически инициирует навигацию на новый URL-адрес, что позволяет создавать динамическую навигацию без перезагрузки страницы, хотя для одностраничных приложений обычно используются другие механизмы, такие как History API, для более тонкого контроля над историей. Доступ к объекту location ограничен политикой одного источника, что означает, что скрипты из одного источника не могут читать или изменять location документов, загруженных из другого источника, за исключением некоторых ограниченных сценариев, что обеспечивает безопасность и предотвращает атаки межсайтового скриптинга. Объект location является незаменимым инструментом для управления навигацией, создания перенаправлений, анализа текущего состояния приложения и реализации маршрутизации на стороне клиента, и его понимание необходимо для любого разработчика, работающего с веб-приложениями.
window.location (и сокращение document.location) отражает URL текущей страницы.
| Свойство / метод | Назначение |
|---|---|
href | полный URL |
pathname | путь без домена (/catalog/item) |
search | строка запроса (?id=5) |
hash | фрагмент (#reviews) |
assign(url) | переход с записью в history |
replace(url) | переход без новой записи в history |
reload() | перезагрузка страницы |
const params = new URLSearchParams(location.search);
const id = params.get('id');
if (!id) {
location.assign('/catalog');
}
Разбор:
- В этом фрагменте используется конструкция
const params = new URLSearchParams(location.search);как точка входа сценария. - Код показывает последовательность действий: получение данных, проверка условий и выполнение целевого действия.
- Ключевые вызовы и свойства опираются на стандартные API JavaScript/браузера, поэтому шаблон легко перенести в реальный проект.
- Такой пример удобно расширять обработкой ошибок, логированием и дополнительной валидацией входных данных.
Чтение location без присваивания безопасно; location.href = '...' и location.assign() инициируют навигацию. Для SPA чаще меняют маршрут через History API или роутер фреймворка, не полную перезагрузку.
Объект history
Объект history — это встроенный объект в браузерной объектной модели, доступный через window.history, который предоставляет интерфейс для управления историей сессии браузера в пределах текущей вкладки, позволяя разработчику перемещаться по страницам, которые пользователь посетил в данной вкладке, и модифицировать историю программно для создания более плавной навигации в одностраничных приложениях. Объект history предоставляет основные методы навигации, такие как back для перехода на предыдущую страницу в истории, forward для перехода на следующую страницу, и go для перехода на страницу с определенным смещением относительно текущей позиции, например, history.go-1 для перехода назад на одну страницу, и эти методы эквивалентны нажатию кнопок навигации браузера. Для более продвинутого управления историей в одностраничных приложениях объект history предоставляет методы pushState и replaceState, которые позволяют добавлять или изменять записи в истории без фактической загрузки нового документа, принимая три аргумента: объект состояния, который может содержать любые данные, связанные с записью, заголовок, который в большинстве браузеров игнорируется, и URL-адрес, который будет отображаться в адресной строке браузера. Когда пользователь нажимает кнопки назад или вперед, или когда вызываются методы back, forward или go, браузер генерирует событие popstate, которое позволяет приложению реагировать на изменение истории и обновлять отображение соответствующим образом, что является основой для клиентской маршрутизации во многих фреймворках, таких как React Router или Vue Router. Важно отметить, что pushState и replaceState изменяют только URL-адрес в адресной строке и добавляют запись в историю, но не вызывают перезагрузку страницы или проверку нового URL-адреса сервером, что делает их идеальными для одностраничных приложений, где навигация обрабатывается на клиенте. Объект history также предоставляет свойство length, которое возвращает количество записей в истории сессии, и свойство state, которое возвращает текущий объект состояния, установленный через pushState или replaceState, что позволяет приложению сохранять и восстанавливать состояние при навигации. Понимание объекта history и его методов является критически важным для создания современных веб-приложений с плавной навигацией и возможностью использования кнопок назад и вперед браузера, что значительно улучшает пользовательский опыт.
window.history хранит стек переходов в рамках одного источника (origin).
| Метод | Действие |
|---|---|
back() | шаг назад |
forward() | шаг вперёд |
go(n) | на n шагов (-1 — назад) |
pushState(state, title, url?) | добавить запись без перезагрузки |
replaceState(state, title, url?) | заменить текущую запись |
history.pushState({ page: 'settings' }, '', '/app/settings');
window.addEventListener('popstate', (event) => {
console.log('Навигация назад/вперёд', event.state);
});
Разбор:
- В этом фрагменте используется конструкция
history.pushState({ page: 'settings' }, '', '/app/settings');как точка входа сценария. - Код показывает последовательность действий: получение данных, проверка условий и выполнение целевого действия.
- Подписка через
addEventListenerсвязывает поведение с действием пользователя и отделяет логику от HTML-разметки. - Ключевые вызовы и свойства опираются на стандартные API JavaScript/браузера, поэтому шаблон легко перенести в реальный проект.
- Такой пример удобно расширять обработкой ошибок, логированием и дополнительной валидацией входных данных.
Событие popstate срабатывает при кнопках "назад/вперёд", не при pushState из скрипта. Данные state — произвольный сериализуемый объект; не кладите туда секреты.
Объект navigator
Объект navigator — это встроенный объект в браузерной объектной модели, доступный через window.navigator, который предоставляет обширную информацию о браузере и операционной системе пользователя, а также о возможностях и настройках устройства, на котором запущено приложение, позволяя разработчику адаптировать поведение и отображение веб-приложения в зависимости от характеристик окружения. Объект navigator содержит множество свойств, включая userAgent, который представляет собой строку, идентифицирующую браузер, его версию и операционную систему, platform, указывающую на платформу, на которой работает браузер, language и languages для определения языка пользователя, cookieEnabled для проверки поддержки и включения кук, onLine для определения состояния подключения к интернету, и hardwareConcurrency для получения количества доступных логических процессоров. Среди более современных свойств объекта navigator важное место занимают mediaDevices для доступа к камере и микрофону, geolocation для получения географического положения пользователя с его согласия, bluetooth для работы с Bluetooth-устройствами, battery для получения информации о состоянии батареи, и permissions для проверки и запроса различных разрешений браузера, что открывает широкие возможности для создания мощных веб-приложений, интегрированных с аппаратными возможностями устройства. Объект navigator также предоставляет методы, такие как registerProtocolHandler для регистрации приложения как обработчика определенных протоколов, и sendBeacon для асинхронной отправки небольших объемов данных на сервер, даже когда страница закрывается, что полезно для аналитики и логирования. Важно отметить, что многие свойства объекта navigator могут быть изменены или подделаны пользователем или браузерными расширениями, поэтому использование navigator для принятия критических решений, связанных с безопасностью или функциональностью, требует осторожности и не должно быть единственным источником информации о возможностях браузера. Объект navigator является ценным инструментом для адаптивной веб-разработки, позволяя создавать приложения, которые корректно работают на различных устройствах и браузерах, используют доступные аппаратные возможности и предоставляют локализованный и персонализированный пользовательский опыт в зависимости от настроек и предпочтений пользователя.
navigator — сведения о браузере и возможностях устройства.
| Свойство / API | Типичное использование |
|---|---|
userAgent | строка клиента (осторожно: подделывается, не для жёсткой логики) |
language / languages | предпочитаемые языки интерфейса |
onLine | есть ли сеть (грубая оценка) |
clipboard | Clipboard API — копирование текста |
share | Web Share API — системное окно "Поделиться" (title, text, url) |
serviceWorker | регистрация фонового скрипта (PWA) |
mediaDevices | камера/микрофон (WebRTC) |
if (!navigator.onLine) {
showBanner('Нет подключения — часть функций недоступна');
}
Разбор:
- В этом фрагменте используется конструкция
if (!navigator.onLine) {как точка входа сценария. - Код показывает последовательность действий: получение данных, проверка условий и выполнение целевого действия.
- Ключевые вызовы и свойства опираются на стандартные API JavaScript/браузера, поэтому шаблон легко перенести в реальный проект.
- Такой пример удобно расширять обработкой ошибок, логированием и дополнительной валидацией входных данных.
Проверка возможностей — 'geolocation' in navigator, 'serviceWorker' in navigator — надёжнее, чем разбор userAgent.
Геолокация — navigator.geolocation
Geolocation API возвращает координаты устройства (GPS, Wi‑Fi, IP). Доступ только по HTTPS (или localhost) и с разрешения пользователя.
Код ITЗагрузка примера кода…
| Метод | Назначение |
|---|---|
getCurrentPosition(success, error?, options?) | координаты один раз |
watchPosition(success, error?, options?) | подписка на изменение; возвращает id |
clearWatch(id) | отменить watchPosition |
Обёртка в Promise удобна с async/await:
function getPosition(options) {
return new Promise((resolve, reject) => {
navigator.geolocation.getCurrentPosition(resolve, reject, options);
});
}
const pos = await getPosition({ timeout: 5000 });
Координаты не подставляйте в URL без согласия пользователя; на сервере всё равно нужна серверная валидация адреса.
Хранение данных на клиенте
BOM и DOM дают несколько уровней хранения:
| API | Где | Кратко |
|---|---|---|
document.cookie | строка с параметрами | сессии, совместимость; HttpOnly — только сервер |
localStorage / sessionStorage | ключ–значение, ~5 МБ | настройки UI, черновики |
| IndexedDB | объекты, большие объёмы | офлайн-кэш, файлы |
Подробное сравнение, лимиты и риски XSS — в хранении данных в браузере. Cookie для авторизации предпочтительнее localStorage.
Cookie — это небольшие фрагменты текстовых данных, которые веб-сервер отправляет веб-браузеру, а браузер сохраняет их на компьютере пользователя и возвращает серверу при каждом последующем запросе к этому серверу, позволяя веб-сайтам запоминать состояние и информацию о пользователе между сессиями, обеспечивая такие функции, как аутентификация, персонализация, хранение предпочтений и отслеживание поведения пользователя. В JavaScript доступ к кукам предоставляется через свойство document.cookie, которое представляет собой строку, содержащую все куки, установленные для текущего домена, и позволяет как читать существующие куки, так и устанавливать новые или изменять существующие путем присваивания строки с определенным форматом, включающим имя, значение, опциональные атрибуты, такие как expires для установки даты истечения, max-age для установки времени жизни в секундах, path для ограничения пути, domain для ограничения домена, secure для отправки только по HTTPS, и SameSite для защиты от межсайтовой подделки запросов. При чтении document.cookie возвращает строку, содержащую все куки, разделенные точкой с запятой, в формате имя=значение, и разработчику приходится парсить эту строку для получения значений конкретных кук, в то время как установка новой куки выполняется путем присвоения строки с именем и значением, при этом существующие куки не перезаписываются, если только не указано совпадающее имя, путь и домен. Куки имеют важные ограничения безопасности и конфиденциальности, включая ограничение размера, обычно около 4 килобайт на куку, ограничение количества кук на домен, обычно до 50, и ограничение на количество кук в браузере в целом, а также подверженность краже и перехвату, если не используются флаги secure и HttpOnly, который запрещает доступ к куке через JavaScript для защиты от XSS-атак. В современной веб-разработке куки используются для управления сессиями пользователей, хранения токенов аутентификации и небольших объемов данных, которые должны быть доступны на сервере при каждом запросе, в то время как для хранения больших объемов данных на клиенте, не требующих отправки на сервер, используются другие механизмы, такие как localStorage и sessionStorage. Важно отметить, что куки подлежат политике SameSite и ограничениям по источникам, что означает, что они не могут быть прочитаны или установлены из другого домена, за исключением определенных сценариев, и что все более строгие законы о конфиденциальности, такие как GDPR, требуют от разработчиков получения согласия пользователя на использование кук, особенно для целей отслеживания и рекламы, что делает управление куками важной частью соблюдения нормативных требований.
Размеры окна и прокрутка
| API | Что измеряет |
|---|---|
window.innerWidth / innerHeight | viewport с полосами прокрутки |
window.outerWidth / outerHeight | всё окно браузера с рамками |
document.documentElement.clientWidth | ширина области просмотра <html> |
window.scrollX, window.scrollY | смещение прокрутки страницы |
window.scrollTo(x, y) | программная прокрутка |
element.scrollIntoView() | прокрутить к элементу |
window.addEventListener('scroll', () => {
const scrolled = window.scrollY;
document.body.classList.toggle('header--compact', scrolled > 80);
}, { passive: true });
Разбор:
- В этом фрагменте используется конструкция
window.addEventListener('scroll', () => {как точка входа сценария. - Код показывает последовательность действий: получение данных, проверка условий и выполнение целевого действия.
- Подписка через
addEventListenerсвязывает поведение с действием пользователя и отделяет логику от HTML-разметки. - Ключевые вызовы и свойства опираются на стандартные API JavaScript/браузера, поэтому шаблон легко перенести в реальный проект.
- Такой пример удобно расширять обработкой ошибок, логированием и дополнительной валидацией входных данных.
Флаг passive: true на scroll/touch подсказывает браузеру, что вы не вызовете preventDefault() — прокрутка остаётся плавной.
Размеры конкретного блока на странице — через getBoundingClientRect() и ResizeObserver, не через window.
screen, open и диалоги
window.screen — физический экран (width, height, availWidth). Нужен редко (полноэкранные режимы, аналитика).
window.open(url, target, features) — новое окно или вкладка. Всплывающие окна часто блокируются, если вызов не из прямого действия пользователя (клик).
alert, confirm, prompt — синхронные диалоги, блокируют главный поток. В продакшене UI лучше строить через разметку и модальные компоненты; нативные диалоги оставляют для отладки и простых учебных примеров.
События жизненного цикла страницы
| Событие | Когда |
|---|---|
DOMContentLoaded | DOM построен, без ожидания картинок |
load | загружены ресурсы (включая изображения) |
beforeunload | уход со страницы (можно показать предупреждение) |
resize | изменился размер окна |
hashchange | изменился #фрагмент в URL |
Инициализацию скриптов, которым нужен готовый DOM, удобно вешать на DOMContentLoaded — см. подключение кода.
Практические правила
- Не смешивайте полную перезагрузку (
location.href = …) и SPA-навигацию без понимания, что history и состояние приложения сбросятся. - Не полагайтесь на
userAgentдля ветвления логики — используйте feature detection. - Тяжёлую работу на
scrollдебаунсьте или заменяйте IntersectionObserver. - Секреты и токены не храните в
history.stateи не передавайте вhashбез необходимости.
Мини-паттерны из продакшена
| Задача | BOM API | Примечание |
|---|---|---|
| Восстановить фильтр каталога после reload | location.search + URLSearchParams | легко поделиться ссылкой с параметрами |
| Сделать кнопку "Назад к списку" в SPA | history.pushState и popstate | важно хранить минимальный state |
| Показать баннер offline | navigator.onLine + online/offline события | статус сети служит UX-подсказкой |
| Фиксировать шапку после прокрутки | scrollY + passive listener | тяжёлые вычисления выносить в requestAnimationFrame |
Эти паттерны помогают строить навигацию и поведение страницы предсказуемо, особенно в связке с событиями и структурой модулей.
Разделение ответственности
- DOM отвечает за содержимое документа (Selection и Range).
- BOM отвечает за URL, историю, окно и окружение браузера (geolocation, хранение).
- Сетевой слой работает через
fetchи асинхронные сценарии. Готовые шаблоны GET/POST с разбором — Fetch / axios — типовые запросы.
Такое разделение ускоряет отладку: источник проблемы находится быстрее, и код становится проще поддерживать в долгую.
Краткий итог
BOM — это window и связанные объекты location, history, navigator, API прокрутки и размеров. DOM меняет страницу; BOM — контекст, в котором страница открыта. Для интерактивности внутри документа сочетайте BOM с событиями и DOM.