JavaScript LinuxWindowsmacOS

JavaScript — Cannot read properties of null (reading addEventListener)

  • Обновлено
  • Чтение ≈ 4 минуты

Краткий ответ

«Cannot read properties of null (reading 'addEventListener')» значит, что querySelector/getElementById вернул null: скрипт запущен до загрузки DOM, селектор неверен или элемент создаётся позже. Подключайте скрипт с defer и проверяйте элемент.

В этой статье
  1. Что означает ошибка
  2. Причины и решения
  3. Пошаговое решение
  4. Примеры

#Что означает ошибка

Сообщение
Cannot read properties of null

Метод getElementById('btn') возвращает null, если элемента с таким id нет в документе в момент вызова. Затем null.addEventListener(...) вызывает TypeError. Это одна из самых частых ошибок JavaScript, и причина всегда в одном из трёх: скрипт выполняется слишком рано, селектор не совпадает, либо элемент создаётся динамически позже.

#Причины и решения

Возможная причинаКак узнатьЧто делать
Скрипт выполняется до загрузки DOMТег script стоит в head и подключён без атрибута defer.Ошибка при открытии страницы.Добавьте defer или переместите скрипт вниз.
Неверный селекторОпечатка в id/классе, либо # и . перепутаны.console.log(el) выводит null.Проверьте имя в HTML.
Элемент создаётся позжеЭлемент появляется после AJAX, рендера фреймворка.В момент вызова его ещё нет.Используйте делегирование событий.
Другая страницаОбщий скрипт запущен на странице без этого элемента.Ошибка только на некоторых страницах.Проверяйте наличие элемента.

#Пошаговое решение

  1. Найдите строку ошибкиОткройте проблемную страницу в браузере, нажмите F12 или Ctrl+Shift+J (обычно Chrome/Edge) → вкладка Console и найдите сообщение Cannot read properties of null (reading 'addEventListener'). Нажмите по ссылке с именем скрипта и строкой: браузер перейдёт на вкладку Sources к месту вызова. Посмотрите, какая переменная слева от .addEventListener равна null. Запомните, на какой странице и после какого действия ошибка появляется. Если код принадлежит стороннему расширению, сначала проверьте страницу в приватном окне без расширений.
  2. Выведите элементВо вкладке Console выполните проверку без изменения страницы, например document.querySelector('#btn'), где #btn замените реальным селектором из проблемной строки. Если вывод null, элемент не найден в текущем документе; если показан HTML-элемент, причина может быть в моменте выполнения или другом контексте. Для getElementById('btn') передавайте имя без #. Если элемент находится внутри iframe или теневого DOM, обычный document.querySelector из основного документа может его не видеть — уточните контекст, не создавайте дубликат кнопки.
  3. Проверьте HTMLОткройте DevTools → Elements (или «Элементы»), нажмите Ctrl+F и найдите id="btn" либо нужный класс. Сравните регистр букв, точное имя и отсутствие лишних пробелов. Проверьте, не используют ли две кнопки одинаковый id — это нарушает корректную идентификацию элемента. Если HTML создаётся шаблонизатором, отредактируйте исходный шаблон или компонент, а не только видимый HTML в DevTools. После сохранения обновите страницу без кэша и вновь выполните селектор из предыдущего шага.
  4. Подключите скрипт правильноЕсли элемент существует, но скрипт исполняется до разбора HTML, откройте исходный HTML-файл и найдите тег <script src="app.js">. Для внешнего обычного скрипта можно добавить defer, чтобы он выполнялся после разбора HTML: <script src="app.js" defer></script>. Альтернатива — обернуть регистрацию обработчиков в document.addEventListener('DOMContentLoaded', () => { ... }). Не используйте оба способа без необходимости и учтите, что модули type="module" уже откладывают выполнение по умолчанию. Перезагрузите страницу и проверьте, исчезла ли ошибка.
  5. Проверьте условиеЕсли один JS-файл загружается на нескольких страницах, а кнопка есть не везде, предусмотрите проверку наличия: const btn = document.querySelector('#btn'); if (btn) { btn.addEventListener('click', handler); }. Сам обработчик handler должен быть определённой функцией, а не результатом её преждевременного вызова. Добавьте временный console.warn для отсутствующего элемента на нужной странице. Так скрипт не будет падать, но если кнопка должна существовать, найдите причину её отсутствия вместо молчаливого пропуска.
  6. Для динамических элементов используйте делегированиеЕсли кнопка появляется после загрузки через JavaScript или фреймворк, регистрация при DOMContentLoaded может быть слишком ранней. В простой странице используйте делегирование на постоянном контейнере: назначьте обработчик родителю, а внутри через event.target.closest('.btn') проверьте нажатый элемент. В React/Vue обычно правильнее назначить обработчик в самом компоненте по правилам фреймворка, а не вручную искать его в DOM. Убедитесь, что обработчик не создаётся повторно на каждом обновлении, иначе события начнут срабатывать несколько раз.
  7. Используйте опциональную цепочкуВыражение btn?.addEventListener('click', handler) не выбросит ошибку при null, но не объяснит, почему кнопка отсутствует. Используйте его только если элемент действительно необязателен. После исправления обновите страницу, откройте Console и нажмите кнопку: ожидается однократный вызов обработчика и отсутствие TypeError. Если ошибка осталась, сохраните сообщение, HTML-селектор, исходный код подключения и информацию о том, когда создаётся элемент; проверьте другие участки, где вызывается .addEventListener.
  8. Пример кода по теме
    index.html
    Атрибут defer откладывает выполнение скрипта до окончания разбора HTML, при этом порядок нескольких скриптов сохраняется.
    <script src="app.js" defer></script>

#Примеры

app.js
Безопасная привязка обработчика и делегирование событий.
document.addEventListener('DOMContentLoaded', () => {
  const btn = document.querySelector('#btn');
  if (!btn) {
    console.warn('Элемент #btn не найден');
    return;
  }
  btn.addEventListener('click', () => console.log('Клик'));
});

// Делегирование для элементов, которые появятся позже
document.addEventListener('click', (e) => {
  const item = e.target.closest('.item');
  if (item) console.log('Элемент', item.dataset.id);
});

Для сборок на React/Vue не используйте getElementById внутри компонента до монтирования: применяйте ref или хуки (useEffect, onMounted). Если ошибка появляется только в продакшене, проверьте, не минифицируются ли id и не блокируют ли расширения браузера DOM-элементы. Справка по методам — MDN.

Так эту ошибку тоже называют

Источники и обновления

Последнее обновление статьи: 1 ноября 2026. Версии программ и интерфейсы меняются — если шаги не совпадают с вашей версией, сверяйтесь с документацией производителя.