Как в чистом JavaScript (Vanilla JS) заменить $(document).ready() и выполнить код после загрузки DOM?
Правильный способ: слушатель события DOMContentLoaded
В чистом JavaScript для выполнения кода после построения DOM (но до полной загрузки изображений и других ресурсов) используется событие DOMContentLoaded на объекте document. Это самый точный аналог jQuery $(document).ready().
Вот как это выглядит:
document.addEventListener('DOMContentLoaded', function() {
// Ваш код, который выполнится после построения DOM
console.log('DOM готов!');
const button = document.getElementById('myButton');
button.addEventListener('click', function() {
alert('Кнопка нажата!');
});
});
Если вы используете современный JavaScript (ES6+), можно записать короче со стрелочной функцией:
document.addEventListener('DOMContentLoaded', () => {
// Ваш код
});
Почему это лучше, чем window.onload?
- DOMContentLoaded срабатывает, как только браузер построил DOM-дерево из HTML. Изображения, стили, фреймы могут ещё загружаться — это не важно.
- window.onload ждёт загрузки ВСЕХ ресурсов (картинки, iframe, стили). Если на странице много тяжёлых изображений, пользователь будет ждать, прежде чем код выполнится.
- К тому же
window.onloadможно назначить только один раз (если написатьwindow.onload = fn, то предыдущий обработчик перезапишется), а черезaddEventListenerможно вешать сколько угодно обработчиков.
Что, если DOM уже готов?
Иногда скрипт может выполниться уже после того, как событие DOMContentLoaded произошло (например, если скрипт загружается асинхронно). В этом случае обработчик не сработает. Чтобы быть уверенным, можно проверить состояние документа:
function domReady(callback) {
if (document.readyState === 'loading') {
// DOM ещё строится — ждём событие
document.addEventListener('DOMContentLoaded', callback);
} else {
// DOM уже готов — вызываем сразу
callback();
}
}
// Использование:
domReady(() => {
console.log('DOM готов!');
});
Проверка на существование jQuery (на всякий случай)
Если вы мигрируете с jQuery и хотите сохранить обратную совместимость, можно написать универсальную функцию:
function ready(fn) {
if (typeof jQuery !== 'undefined') {
// Если jQuery подключён — используем его
jQuery(fn);
} else {
// Иначе — чистый JS
if (document.readyState !== 'loading') {
fn();
} else {
document.addEventListener('DOMContentLoaded', fn);
}
}
}
// Теперь можно писать:
ready(function() {
console.log('Сработает в любом случае');
});
Важное замечание про атрибут defer
Если вы подключаете скрипт через тег <script> с атрибутом defer, то он выполнится автоматически после построения DOM, и оборачивать код в DOMContentLoaded не нужно:
<script src="script.js" defer></script>
Но если вы используете async или обычный скрипт в <head>, то без DOMContentLoaded не обойтись.
Таким образом, лучшая практика для Vanilla JS — использовать document.addEventListener('DOMContentLoaded', handler) или универсальную обёртку с проверкой состояния. Это надёжно, просто и полностью заменяет jQuery $.ready().
Альтернативный подход: размещение скрипта в конце body
Самый простой способ, который не требует никаких событий — просто поместить ваш тег <script> перед закрывающим тегом </body>. К тому моменту, как браузер дойдёт до скрипта, весь DOM уже будет построен (ведь HTML парсится сверху вниз).
<!DOCTYPE html>
<html>
<head>
<title>Пример</title>
</head>
<body>
<button id="myButton">Нажми меня</button>
<!-- Скрипт в конце body -->
<script>
const button = document.getElementById('myButton');
button.addEventListener('click', () => {
alert('Кнопка нажата!');
});
console.log('DOM готов, скрипт выполняется');
</script>
</body>
</html>
Этот метод работает без единого обработчика событий. Однако у него есть минусы:
- Скрипт блокирует парсинг страницы, пока загружается и выполняется (если не использовать
async/defer). - Если скрипт внешний (
src="..."), его загрузка задержит отрисовку. - Не подходит, если вы хотите выполнить код до того, как страница полностью отрендерится (например, показать спиннер загрузки).
Поэтому для серьёзных проектов рекомендую использовать DOMContentLoaded из первого ответа. Но для быстрых прототипов или учебных примеров — размещение скрипта в конце <body> вполне допустимо.