Браузер и BOM
BOM, навигация и жизненный цикл страницы, политика одного источника, таймеры, web storage и web workers.
11 вопросов
JuniorТеорияОчень частоЧто делают setTimeout и setInterval, и как clearTimeout и clearInterval их отменяют?
Что делают setTimeout и setInterval, и как clearTimeout и clearInterval их отменяют?
setTimeout(fn, ms) планирует однократный запуск fn примерно через ms миллисекунд; setInterval(fn, ms) запускает его повторно каждые ms, пока не остановят. Каждый возвращает числовой id таймера. Передайте этот id в clearTimeout(id), чтобы отменить ожидающий таймаут, или в clearInterval(id), чтобы остановить повторяющийся интервал. Задержка — это минимум, а не гарантия, ведь колбэк ждёт свободный стек вызовов.
Типичные ошибки
- ✗Думать, что задержка точна, а не минимум, ждущий освобождения стека
- ✗Передавать функцию в
clearTimeoutвместо возвращённого id таймера - ✗Забывать, что
setIntervalсрабатывает вечно, пока не вызванclearInterval
Уточняющие вопросы
- →Почему колбэки
setIntervalмогут накладываться или смещаться, и как рекурсивныйsetTimeoutэтого избегает? - →Что за минимальная задержка ~4мс в браузере для глубоко вложенных таймеров?
JuniorТеорияЧастоВ чём разница между window и document, и что дают location, history и navigator?
В чём разница между window и document, и что дают location, history и navigator?
window — глобальный объект и корень страницы; document — его потомок, дерево DOM содержимого страницы. BOM предоставляет браузерные объекты на window: location читает и меняет текущий URL, history ходит по стеку сессии через back()/forward(), а navigator сообщает сведения о браузере и платформе, например userAgent. BOM формально не стандартизирован.
Типичные ошибки
- ✗Считать
windowиdocumentвзаимозаменяемыми, а не родителем и потомком - ✗Путать
history(навигация по сессии) сlocation(текущий URL) - ✗Полагать, что BOM стандартизирован так же, как DOM
Уточняющие вопросы
- →Почему глобальные объявления
varпопадают наwindow, а объявленияlet— нет? - →Как
history.pushStateпозволяет одностраничному приложению менять URL без перезагрузки?
JuniorТеорияЧастоЧем localStorage, sessionStorage и cookie различаются по времени жизни, размеру и области?
Чем localStorage, sessionStorage и cookie различаются по времени жизни, размеру и области?
localStorage хранится для origin, пока его явно не очистят, даже после перезапуска браузера. sessionStorage живёт только для текущей вкладки и стирается при её закрытии. Cookie тоже привязаны к origin, но истекают по заданной дате, ограничены ~4КБ и отправляются с каждым HTTP-запросом на сервер. Оба хранилища держат ~5МБ строк и остаются только на клиенте.
Типичные ошибки
- ✗Считать, что
sessionStorageобщий для вкладок — он изолирован по вкладке - ✗Думать, что значения хранилища могут быть объектами, хотя оба хранят только строки
- ✗Забывать, что cookie едут с каждым запросом, в отличие от Web Storage
Уточняющие вопросы
- →Почему объект нужно пропускать через
JSON.stringifyперед записью вlocalStorage? - →Как продублированная вкладка может разделять состояние, если
sessionStorageпривязан к вкладке?
MiddleТеорияЧастоЧем отличаются DOMContentLoaded и load, и как defer и async меняют тайминг скриптов?
Чем отличаются DOMContentLoaded и load, и как defer и async меняют тайминг скриптов?
DOMContentLoaded срабатывает, когда HTML разобран и DOM построен, до загрузки картинок и стилей; load срабатывает позже, после загрузки всех подресурсов. Обычный <script> блокирует разбор, пока скачивается и выполняется. defer скачивается параллельно, но выполняется после разбора, в порядке документа, прямо перед DOMContentLoaded. async тоже скачивается параллельно, но выполняется сразу по прибытии, поэтому порядок не гарантирован и он может выполниться до или после разбора.
Типичные ошибки
- ✗Считать
DOMContentLoadedиloadодним и тем же моментом - ✗Ожидать, что
async-скрипты выполнятся в порядке документа - ✗Полагать, что
deferблокирует разбор HTML при скачивании
Уточняющие вопросы
- →Почему
deferпредпочтительнее размещения<script>в конце<body>? - →Почему
async-скрипт аналитики может игнорировать порядок выполнения, а сборка фреймворка — нет?
MiddleТеорияЧастоЧто на самом деле делает setTimeout(fn, 0), и чем отличаются debounce, throttle и requestAnimationFrame?
Что на самом деле делает setTimeout(fn, 0), и чем отличаются debounce, throttle и requestAnimationFrame?
setTimeout(fn, 0) не запускается сразу — он ставит fn как макрозадачу после текущего синхронного кода (а при вложенности браузер ограничивает ~4мс). Debounce откладывает функцию, пока вызовы не затихнут на время паузы; throttle запускает её не чаще раза за интервал. requestAnimationFrame планирует колбэк прямо перед следующей перерисовкой, синхронизируясь с обновлением экрана, что делает анимации плавнее, чем setInterval с фиксированной задержкой.
Типичные ошибки
- ✗Думать, что
setTimeout(fn, 0)запускается синхронно, а не после текущего кода - ✗Путать debounce (ждать тишины) с throttle (ограничение за интервал)
- ✗Использовать
setIntervalдля анимации вместо синхронизации с перерисовкой уrequestAnimationFrame
Уточняющие вопросы
- →Почему
requestAnimationFrameприостанавливается на фоновой вкладке, аsetIntervalпродолжает? - →Что выбрать для поля поиска по мере ввода — debounce или throttle, и почему?
SeniorТеорияЧастоКак requestAnimationFrame, таймеры и микрозадачи связаны с reflow и repaint, и как помогают worker'ы?
Как requestAnimationFrame, таймеры и микрозадачи связаны с reflow и repaint, и как помогают worker'ы?
Микрозадачи (колбэки Promise) опустошаются после текущей задачи, но до отрисовки; макрозадачи вроде setTimeout выполняются позже; requestAnimationFrame выполняется прямо перед следующей перерисовкой, идеален для визуальных обновлений. Изменения раскладки запускают reflow (пересчёт геометрии, дорогой и каскадный), а изменения только стиля — более дешёвый repaint. Группируйте чтения/записи DOM против thrashing, выносите тяжёлую работу CPU в Web Worker и вызывайте removeEventListener на удалённых узлах против утечек.
Типичные ошибки
- ✗Путать reflow (геометрия, дорого) с repaint (только стиль, дешевле)
- ✗Чередовать чтения и записи DOM, форсируя повторную синхронную раскладку
- ✗Оставлять слушатели на удалённых узлах, удерживая их как утечку памяти
Уточняющие вопросы
- →Почему чтение
offsetHeightпосле записи стиля форсирует синхронный reflow? - →Как сгруппировать обновления анимации внутри одного колбэка
requestAnimationFrame?
MiddleТеорияИногдаЧто такое политика одного источника, и как с ней связаны CORS и кросс-доменные iframe?
Что такое политика одного источника, и как с ней связаны CORS и кросс-доменные iframe?
Источник — это тройка из схемы, хоста и порта; два URL имеют один источник, только когда совпадают все три. Политика одного источника не даёт странице читать ответы или DOM другого источника, блокируя кражу данных. CORS позволяет серверу разрешить доступ, отправив Access-Control-Allow-Origin, ослабляя ограничение на чтение для запросов. Кросс-доменный iframe всё равно отрисовывается, но родитель не может трогать его DOM, и они общаются только через postMessage.
Типичные ошибки
- ✗Забывать, что порт (и схема) — часть источника, а не только хост
- ✗Считать, что CORS задаёт клиент, а не разрешает сервер
- ✗Полагать, что родитель может читать DOM кросс-доменного iframe напрямую
Уточняющие вопросы
- →Почему предзапрос
OPTIONS(preflight) CORS предшествует некоторым кросс-доменным запросам? - →Как
postMessageбезопасно передаёт данные через границу кросс-доменного iframe?
MiddleТеорияИногдаЧто такое Web Worker, как postMessage общается с ним, и почему он не может трогать DOM?
Что такое Web Worker, как postMessage общается с ним, и почему он не может трогать DOM?
Web Worker выполняет скрипт в отдельном фоновом потоке, поэтому тяжёлая работа не блокирует основной поток интерфейса. У него нет общей памяти со страницей: данные обменивают через postMessage, и каждая сторона читает их событием onmessage / message. Worker не имеет доступа к DOM, window или document, поэтому не может обновлять страницу напрямую — он шлёт результаты обратно, чтобы основной поток их отрисовал.
Типичные ошибки
- ✗Думать, что worker может напрямую читать или писать DOM
- ✗Ожидать, что
postMessageвернёт значение, а не вызовет асинхронное событиеmessage - ✗Полагать, что worker делит переменные со страницей, а не копирует данные
Уточняющие вопросы
- →Как Transferable-объекты позволяют
postMessageпередатьArrayBufferбез копирования? - →Когда выбрать Web Worker вместо асинхронного
awaitдля долгого вычисления?
SeniorТеорияИногдаКак модель безопасности браузера, инкапсуляция shadow DOM и History API поддерживают маршрутизацию SPA?
Как модель безопасности браузера, инкапсуляция shadow DOM и History API поддерживают маршрутизацию SPA?
Модель безопасности изолирует источники (схема, хост, порт): политика одного источника блокирует кросс-доменное чтение DOM и ответов, чтобы недоверенный контент не крал данные. Shadow DOM добавляет вторую границу внутри одного источника — его дерево и стили инкапсулированы и отделены от документа. Маршрутизация SPA использует History API: pushState/replaceState меняют URL и добавляют записи без перезагрузки, а обработчик popstate перерисовывает виды при «назад»/«вперёд», так что навигация остаётся на клиенте.
Типичные ошибки
- ✗Думать, что
pushStateсам вызываетpopstate, а не только «назад»/«вперёд» - ✗Считать, что shadow DOM ослабляет политику одного источника между источниками
- ✗Полагать, что History API требует перезагрузки сервера для смены URL
Уточняющие вопросы
- →Как роутер SPA избегает поломки прямой ссылки при жёсткой перезагрузке?
- →Почему инкапсуляция shadow DOM не ослабляет кросс-доменную границу безопасности?