Всегда ли JavaScript выполняется после события onload
Что проверяют
Знаете ли вы, как браузер разбирает страницу и в какой момент выполняется каждый скрипт. Следом обычно спрашивают про разницу async и defer и про то, что будет, если подписаться на load уже после него.
Как отвечать
Нет, не всегда. Большая часть JavaScript выполняется до load, а часть может выполниться и после.
- обычный
<script>: блокирует разбор HTML и выполняется сразу, как только парсер до него дошёл. Скрипт в конце<body>тоже выполняется доDOMContentLoaded, картинки к этому моменту ещё грузятся; defer: скачивается параллельно, выполняется после разбора документа, строго по порядку, доDOMContentLoaded. Скриптыtype="module"по умолчанию ведут себя так же;async: выполняется, как только скачался, порядок не гарантирован, может сработать и до, и послеDOMContentLoaded;DOMContentLoaded: DOM построен, синхронные и отложенные скрипты выполнены, картинки и iframe могут ещё грузиться;load: загружены все ресурсы документа, включая картинки, стили и iframe. Картинки сloading="lazy"вне экрана его не задерживают.
После load код тоже выполняется: динамически вставленные скрипты, обработчики событий, setTimeout, ответы fetch. Текущее состояние страницы видно в document.readyState: loading, interactive, complete. В Next.js похожая настройка есть у next/script: стратегия lazyOnload грузит скрипт уже после загрузки страницы.
Где спотыкаются
Считают, что скрипт в конце <body> выполняется после загрузки всех ресурсов. Он выполняется во время разбора, до DOMContentLoaded.
Вешают обработчик load из кода, который сам загрузился асинхронно, когда событие уже прошло. Обработчик молча не вызовется, поэтому сначала проверяют document.readyState === 'complete'.
Забывают про кэш возврата (bfcache): при переходе «назад» страница восстанавливается из памяти, и load повторно не срабатывает. Для такого случая есть событие pageshow с флагом persisted.