5 JavaScript API, которые должен знать каждый frontend-разработчик
5 нативных JavaScript API для frontend: IntersectionObserver, ResizeObserver, AbortController, Clipboard API и View Transitions.
Пять нативных браузерных API, которые стоит изучить прямо сейчас: IntersectionObserver, ResizeObserver, AbortController, Clipboard API и View Transitions API. Каждый из них заменяет распространённую стороннюю зависимость платформенным примитивом, доступным во всех актуальных браузерах.
Большинство из нас приходит к этому через боль: подключаем целую библиотеку ради кнопки копирования или тратим полдня на поисковую строку, которая раз за разом отрисовывает устаревшие результаты — и лишь потом обнаруживаем, что браузер давно умеет это из коробки. Если вы уже используете fetch, localStorage и DOM, но не знакомы с более новыми observer- и utility-API, перед вами — короткий список, который позволит удалить одну-две библиотеки. Всё описанное ниже — это нативные API веб-платформы, а не сторонние REST-сервисы вроде TMDB или Unsplash: никаких ключей, никакого сервера, никаких накладных расходов помимо браузера, на который вы уже ориентируетесь. Для каждого API приводятся: однострочное определение, минимальный рабочий пример, реальный сценарий использования и честная заметка о поддержке.
Ключевые выводы
- IntersectionObserver сообщает, когда элемент входит в область видимости или покидает её, без использования scroll-обработчиков; он является Baseline-совместимым во всех браузерах с марта 2019 года.
- ResizeObserver реагирует на изменение собственных размеров элемента — content-box или border-box, — что делает возможными контейнерно-зависимые компоненты там, где событие
resizeокна бессильно. - AbortController — стандартное решение для race condition в React: передайте
controller.signalвfetchи вызовитеcontroller.abort()при очистке эффекта, чтобы устаревший ответ не мог перезаписать актуальный UI. navigator.clipboard.writeText()— промис-ориентированная замена устаревшему хаку сdocument.execCommand('copy'), однако работает только в безопасном контексте (HTTPS или localhost).- Same-document View Transitions получили статус Baseline Newly available 14 октября 2025 года и деградируют корректно, поэтому их безопасно использовать с проверкой
if (document.startViewTransition).
IntersectionObserver: браузерный API на замену scroll-обработчикам
IntersectionObserver асинхронно сообщает, когда целевой элемент входит в область видимости (viewport) или покидает её (или любой элемент-предок), что позволяет реализовать ленивую загрузку, бесконечную прокрутку и аналитику видимости без единого scroll-обработчика. Baseline-совместимость во всех браузерах достигнута с марта 2019 года. Scroll-обработчики срабатывают десятки раз в секунду в основном потоке и вынуждают вычислять геометрию вручную; observer же пакетирует эту работу за пределами критического пути и вызывает колбэк только при реальном изменении видимости.
const observer = new IntersectionObserver((entries) => {
for (const entry of entries) {
if (entry.isIntersecting) {
entry.target.src = entry.target.dataset.src; // загружаем только при появлении в viewport
observer.unobserve(entry.target);
}
}
});
document.querySelectorAll('img[data-src]').forEach((img) => observer.observe(img));
Этот код реализует ленивую загрузку изображений по мере прокрутки. Та же проверка isIntersecting управляет sentinel-элементами для бесконечной прокрутки и аналитикой просмотров. Записи сессий для длинных лент наглядно демонстрируют эффект: изображения за пределами экрана и события отслеживания разрешаются только при появлении соответствующих строк в viewport, а не все сразу при загрузке. Заменяет react-intersection-observer и самописную scroll-математику в большинстве случаев. (Примечание: опция trackVisibility по-прежнему экспериментальна и не является Baseline. Используйте только isIntersecting.)
Discover how at OpenReplay.com.
ResizeObserver: реакция на изменение размеров элемента
Используйте ResizeObserver, а не событие resize окна, когда компонент должен реагировать на собственные размеры: он сообщает об изменениях content-box и border-box на уровне элемента, что делает возможными контейнерно-зависимые компоненты. Обработчик window.resize сообщает об изменении viewport; он ничего не знает о панели, которая сузилась из-за открытия боковой панели.
const ro = new ResizeObserver((entries) => {
for (const entry of entries) {
const { width } = entry.contentRect;
entry.target.classList.toggle('is-narrow', width < 400);
}
});
ro.observe(document.querySelector('.card'));
Здесь карточка переключается в компактный макет на основе собственной ширины — это container query на JavaScript. Является Baseline-совместимым во всех актуальных браузерах и заменяет библиотеки вроде element-resize-detector. Если в консоли появляется предупреждение ResizeObserver loop, в большинстве случаев оно безвредно и означает, что вы изменяете размер внутри колбэка.
AbortController: отмена запросов и устранение race condition
AbortController — стандартное решение для race condition в React: передайте controller.signal в fetch, вызовите controller.abort() при очистке эффекта, и устаревший ответ никогда не перезапишет актуальный UI после быстрой повторной навигации. AbortSignal доступен во всех браузерах с апреля 2018 года.
useEffect(() => {
const controller = new AbortController();
fetch(`/api/results?q=${query}`, { signal: controller.signal })
.then((res) => res.json())
.then(setResults)
.catch((err) => {
if (err.name !== 'AbortError') throw err;
});
return () => controller.abort(); // отмена при размонтировании или новом запросе
}, [query]);
Классическая ошибка, которую это устраняет, хорошо видна в записях сессий: пользователь быстро печатает, более ранний медленный ответ приходит последним, и устаревшие данные перекрывают текущее представление. Отмена выполняющегося запроса при очистке делает это невозможным. Для таймаутов контроллер можно не создавать вручную. AbortSignal.timeout() работает во всех браузерах с апреля 2024 года и прерывает запрос с ошибкой TimeoutError, тогда как отмена по инициативе пользователя выбрасывает AbortError, поэтому один блок catch позволяет различить их:
fetch(url, { signal: AbortSignal.timeout(5000) });
Это заменяет флаги isMounted и axios.CancelToken.
Clipboard API: копирование в буфер обмена без хака с execCommand
navigator.clipboard.writeText() — современная, промис-ориентированная замена устаревшему хаку с document.execCommand('copy'). Важно помнить, что она работает только в безопасном контексте (HTTPS или localhost).
copyBtn.addEventListener('click', async () => {
await navigator.clipboard.writeText(snippet);
copyBtn.textContent = 'Copied!';
});
Это та самая кнопка «скопировать фрагмент кода», которая есть на каждом сайте с документацией. Запись в буфер обмена является Baseline-совместимой и надёжной; чтение — по возможности. readText() возвращает пустую строку, если в буфере нет текста, а Firefox накладывает на чтение более строгие ограничения, чем на запись. Поэтому копирование — надёжный путь, а чтение из буфера лучше рассматривать как прогрессивное улучшение. Заменяет clipboard.js.
View Transitions API: нативная анимация изменений DOM
View Transitions анимируют переходы между состояниями DOM с помощью document.startViewTransition(() => updateDOM()). Поскольку API деградирует корректно (анимации нет, но DOM всё равно обновляется в неподдерживаемых браузерах), его безопасно использовать сегодня с проверкой if (document.startViewTransition). Same-document-переходы получили статус Baseline Newly available 14 октября 2025 года и работают в Chrome 111+, Edge 111+, Firefox 144+ и Safari 18+.
function updatePage(newContent) {
if (!document.startViewTransition) {
render(newContent); // запасной вариант: мгновенное обновление без анимации
return;
}
document.startViewTransition(() => render(newContent));
}
Используйте для переключения вкладок, навигации от списка к деталям и изменений фильтров — тех crossfade-эффектов и морфинга общих элементов, ради которых иначе пришлось бы подключать Framer Motion. Проверка startViewTransition() гарантирует, что в неподдерживаемых браузерах изменение просто применяется мгновенно. Обратите внимание: cross-document-переходы имеют более узкую поддержку — Chrome 126+, Edge 126+ и Safari 18.2+, но пока не поддерживаются в Firefox, поэтому не следует смешивать эти два случая.
Дополнительно: structuredClone и особенность fetch
Возьмите один из этих API в следующей задаче и удалите зависимость, которую он заменяет: замените scroll-обработчик на IntersectionObserver или оберните поисковый запрос в AbortController. Ещё одно полезное дополнение: structuredClone() выполняет глубокое копирование объектов без обходного пути через JSON.parse(JSON.stringify(...)) и сохраняет Date, Map, Set и типизированные массивы. Однако он выбрасывает DataCloneError для функций и DOM-узлов, поэтому предназначен для данных, а не для живых объектов (Baseline с марта 2022 года). И если fetch по-прежнему является вашей основой, помните: его промис не отклоняется при HTTP 404 или 500 — только при сетевой ошибке. Проверяйте response.ok самостоятельно.
Часто задаваемые вопросы
В чём разница между IntersectionObserver и ResizeObserver?
IntersectionObserver сообщает, когда элемент входит в viewport или покидает его (или любой элемент-предок), — это основа для ленивой загрузки, бесконечной прокрутки и аналитики видимости. ResizeObserver сообщает об изменениях собственных размеров элемента — content-box или border-box, — что лежит в основе контейнерно-зависимых макетов. IntersectionObserver отвечает на вопрос «виден ли элемент», ResizeObserver — «каков его размер». Это разные задачи, и ни один из них не заменяет событие resize окна в части изменения viewport.
Что использовать для отмены fetch-запросов: AbortSignal.timeout() или ручной AbortController?
Используйте AbortSignal.timeout(), когда нужен только фиксированный таймаут: он автоматически прерывает запрос через заданное количество миллисекунд с ошибкой TimeoutError и не требует переменной контроллера. Используйте ручной AbortController, когда отмена инициируется событием, которым вы управляете сами, — например, при очистке React-эффекта при размонтировании или повторной навигации, где вы вызываете controller.abort() вручную. Оба варианта выбрасывают разные ошибки — TimeoutError и AbortError соответственно, — поэтому один блок catch позволяет их различить.
Почему navigator.clipboard.writeText() не работает на моём локальном сервере разработки?
navigator.clipboard.writeText() работает только в безопасном контексте — то есть по HTTPS или на localhost. Если вы обращаетесь к dev-серверу по обычному HTTP-адресу, например по локальному IP или имени хоста, отличному от localhost, браузер блокирует запись в буфер обмена и промис отклоняется. Используйте localhost или настройте HTTPS. Чтение через readText() ограничено ещё строже, особенно в Firefox, поэтому рассматривайте запись как надёжный путь, а чтение из буфера — как прогрессивное улучшение.
Безопасно ли использовать View Transitions API, если некоторые браузеры его не поддерживают?
Да, поскольку API деградирует корректно. Перед вызовом добавьте проверку if (document.startViewTransition); в браузерах без поддержки обновление DOM всё равно выполнится — просто мгновенно, без анимации. Same-document-переходы получили статус Baseline Newly available 14 октября 2025 года и работают в Chrome 111+, Edge 111+, Firefox 144+ и Safari 18+. Cross-document-переходы имеют более узкую поддержку: Chrome 126+, Edge 126+ и Safari 18.2+, и пока не поддерживаются в Firefox.
Gain control over your UX
See how users are using your site as if you were sitting next to them, learn and iterate faster with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.
Star on GitHub12k