Объектная модель браузера (BOM)
DOM и 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: что запомнить
BOM — API окна вкладки, не DOM-дерева страницы. Три опоры:
- Где пользователь —
location, параметры URL. - Как попал и куда может вернуться —
history. - Среда —
navigator, размеры окна, сеть (onLine, Connection API).
С этой схемой проще связать API с маршрутизацией и адаптивным UI.
Объект 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
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 — сведения о браузере и возможностях устройства.
| Свойство / 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.
Размеры окна и прокрутка
| 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.