Кратко
СкопированоСовременный JavaScript используется не только в браузерах. Среда, в которой он запускается, будь то браузер, сервер или что-то ещё, называется окружением.
У разных окружений разные возможности и функциональность. В этой статье рассмотрим браузерное окружение и браузерную модель документа.
Окружение предоставляет языку дополнительные возможности и функции. Браузерное окружение, например, даёт возможность работать со страницами сайтов.
Представление этих дополнительных возможностей и функциональности в виде объектов, к которым у языка есть доступ — это объектная модель.
В случае с браузерным окружением — это объектная модель браузера (Browser Object Model, BOM). Она предоставляет доступ к navigator, location, fetch и другим объектам.
/* BOM | __________________________|______________________________________ | | | | | |navigator screen location fetch history ...*/
/*
BOM
|
__________________________|______________________________________
| | | | | |
navigator screen location fetch history ...
*/
Объект navigator содержит информацию о браузере: название, версия, платформа, доступные плагины, доступ к буферу обмена и прочее. Это один из самых больших объектов в окружении.
Так, например, может выглядеть содержимое этого объекта в Safari:

Или, например, так в Chrome:

С помощью этого объекта можно узнать, разрешён ли доступ к кукам, получить доступ к буферу обмена, геолокации, узнать, с какого браузера пользователь смотрит на страницу через user.
Забавный факт: поле user объекта navigator часто используется, чтобы определять, в каком именно браузере пользователь смотрит страницу сайта. Но читать его глазами достаточно трудно, поэтому лучше это дело оставить какому-нибудь парсеру.
Также с помощью navigator можно зарегистрировать Service Worker.
screen
СкопированоОбъект screen содержит информацию об экране браузера.

width и height указывают ширину и высоту экрана в пикселях соответственно. availметрики указывают, сколько ширины и высоты доступно — то есть ширину и высоту с учётом интерфейсных деталей браузера типа полос прокрутки.
pixel указывает количество битов на один пиксель экрана.
location
СкопированоОбъект location даёт возможность узнать, на какой странице мы находимся (какой у неё URL) и перейти на другую страницу программно.
Например, для страницы https://www.google.com?search?sxsrf=ALekK02Nk... этот объект будет содержать:

Внутри него есть полезные поля для того, чтобы искать нужную часть адреса.
hrefсодержит URL целиком, включая в себя полный адрес хоста, страницы и все query-параметры.hostиhostnameуказывают имя хоста. Разница между ними в том, чтоhostвключает в себя порт. Если бы мы стучались не на[google, а на. com ] ( http : / / google . com ) google, то. com : 8080 hostсодержал бы значениеwww, в то время как. google . com : 8080 hostnameостался бы тем же.pathnameуказывает путь от корня адреса до текущей страницы.searchуказывает query-параметры, которые находятся в адресной строке, если они есть.hashуказывает хеш (ID элемента после#) страницы. Его ещё называют якорем, потому что при переходе на страницу с хешем браузер найдёт элемент с ID, равным этому хешу, и прокрутит страницу к этому элементу.
Если мы хотим изменить адрес и перейти на другую страницу, мы можем указать новый location:
location.href = 'https://yandex.ru'
location.href = 'https://yandex.ru'
И браузер перейдёт на страницу с адресом https://yandex.ru.
fetch
Скопированоfetch предоставляет возможность работы с сетью, с его помощью можно отправлять запросы на сервер.
fetch('http://example.com/movies.json') .then((response) => { return response.json() }) .then((data) => { console.log(data) })
fetch('http://example.com/movies.json')
.then((response) => {
return response.json()
})
.then((data) => {
console.log(data)
})
history
Скопированоhistory даёт доступ к истории браузера, которая ограничена текущей вкладкой. То есть с её помощью можно перейти на страницу назад, только если мы пришли с неё.
Чтобы перемещаться по истории назад и вперёд, можно использовать методы back и forward:
// Перешли на страницу назадhistory.back()// Перешли на страницу вперёдhistory.forward()
// Перешли на страницу назад
history.back()
// Перешли на страницу вперёд
history.forward()
Для более точного управления историей рекомендуется использовать push и replace.
Методы push и replace принимают три параметра:
state— любые данные, которые связаны с переходом;unused— неиспользуемый параметр, который существует по историческим причинам;url(необязательный) — url адрес новой записи в истории.
// state — данные для новой записи в историиconst state = { user_id: 5 }// unused — для совместимости рекомендуется передавать пустую строкуconst unused = ''// url — url адрес который будет добавлен в адресную строкуconst url = '/another-page/'history.pushState(state, unused, url)
// state — данные для новой записи в истории
const state = { user_id: 5 }
// unused — для совместимости рекомендуется передавать пустую строку
const unused = ''
// url — url адрес который будет добавлен в адресную строку
const url = '/another-page/'
history.pushState(state, unused, url)
Браузер «перейдёт» на страницу /another. Перейдёт не по-настоящему, потому что страница не перезагрузится, а лишь сменит адрес в строке. Это удобно при работе с одностраничными приложениями, когда мы не хотим, чтобы страница перезагружалась.
localStorage , sessionStorage
СкопированоЛокальные хранилища используются, чтобы хранить какие-то данные в браузере пользователя.
Они удобны, когда мы не хотим отправлять данные на сервер, потому что они, например, промежуточные, или нужны только на клиенте.
Допустим, у нас есть форма из 5 шагов, и мы хотим, чтобы все введённые данные сохранились, и пользователь, закрыв браузер и через какое-то время вернувшись, мог не набирать их заново.
function saveToStorage(data) { try { window.localStorage.setItem('some-key', JSON.stringify(data)) } catch { alert('Failed to save data to local storage.') }}function loadFromStorage() { try { return JSON.parse(window.localStorage.getItem('some-key')) } catch { alert('Failed to load data from local storage.') }}// Код обработки формыfunction nextStep() { // При переходе сохраняем всё, что введено saveToStorage(formData)}
function saveToStorage(data) {
try {
window.localStorage.setItem('some-key', JSON.stringify(data))
} catch {
alert('Failed to save data to local storage.')
}
}
function loadFromStorage() {
try {
return JSON.parse(window.localStorage.getItem('some-key'))
} catch {
alert('Failed to load data from local storage.')
}
}
// Код обработки формы
function nextStep() {
// При переходе сохраняем всё, что введено
saveToStorage(formData)
}
Разница между local и session в длительности хранения данных. Данные из session сотрутся, когда пользователь закроет вкладку с приложением. Данные же из local не стираются сами по себе.
На практике
Скопированосоветует
СкопированоЧтобы проверить, есть ли в navigator необходимая вам фича, используйте in:
if ('bluetooth' in navigator) { // Есть доступ к Bluetooth API}if ('serviceWorker' in navigator) { // Есть доступ к Service Worker API}
if ('bluetooth' in navigator) {
// Есть доступ к Bluetooth API
}
if ('serviceWorker' in navigator) {
// Есть доступ к Service Worker API
}
screen
СкопированоЧтобы узнать, сколько пикселей занимает по ширине экран без полосы прокрутки (актуально для Windows, где полоса прокрутки отнимает какое-то пространство), используйте avail:
// Без учёта полосыconst screenWidth = screen.width// С учётом полосы прокруткиconst withoutScrollBar = screen.availWidth
// Без учёта полосы
const screenWidth = screen.width
// С учётом полосы прокрутки
const withoutScrollBar = screen.availWidth
location
СкопированоЧтобы программно перейти на другую страницу, используйте location.
Перейти по адресу на текущем сайте:
location.href = '/another-page'
location.href = '/another-page'
Чтобы перейти на другой сайт, укажите его URL полностью:
location.href = 'https://google.com'
location.href = 'https://google.com'
Чтобы узнать полный путь от корня сайта, используйте location:
// https://out-great-service.io/full/path/to/current/pageconst path = location.pathnameconsole.log(path)// '/full/path/to/current/page'
// https://out-great-service.io/full/path/to/current/page
const path = location.pathname
console.log(path)
// '/full/path/to/current/page'
history
СкопированоЧтобы изменить адрес без перезагрузки страницы, используйте history:
history.pushState(null, '', '/new/page/url')
history.pushState(null, '', '/new/page/url')
Для передачи данных, ассоциированных с переходом, используйте первый аргумент в history:
const transitionData = { userName: 'Alex' }history.pushState(transitionData, '', '/new/page/url')
const transitionData = { userName: 'Alex' }
history.pushState(transitionData, '', '/new/page/url')
После изменения url может потребоваться изменить заголовок - используйте document.
document.title = 'Это новая страница!'
document.title = 'Это новая страница!'
localStorage
СкопированоИспользуйте функции-обёртки, чтобы получать доступ к хранилищу безопасно и не забывать превращать данные в JSON-строку при записи и в объект при чтении:
function saveToStorage(key, data) { try { // Если браузер не поддерживает localStorage, // блок try обезопасит код от неожиданной ошибки window.localStorage.setItem(key, JSON.stringify(data)) } catch { console.error('Failed to save data to local storage.') }}function loadFromStorage(key) { try { return JSON.parse(window.localStorage.getItem(key)) } catch { console.error('Failed to load data from local storage.') }}saveToStorage('user', {name: 'Alex', age: 26})loadFromStorage('user')
function saveToStorage(key, data) {
try {
// Если браузер не поддерживает localStorage,
// блок try обезопасит код от неожиданной ошибки
window.localStorage.setItem(key, JSON.stringify(data))
}
catch {
console.error('Failed to save data to local storage.')
}
}
function loadFromStorage(key) {
try {
return JSON.parse(window.localStorage.getItem(key))
}
catch {
console.error('Failed to load data from local storage.')
}
}
saveToStorage('user', {name: 'Alex', age: 26})
loadFromStorage('user')