JavaRush /Курсы /Модуль 1: Web Core /Разбор типичных ошибок при работе с событиями

Разбор типичных ошибок при работе с событиями

Модуль 1: Web Core
23 уровень , 4 лекция
Открыта

1. Ошибка: обработчик не срабатывает

Симптомы: Клик по кнопке — ничего не происходит. Вводишь в поле — а в консоли тишина. Жмёшь на ссылку — но обработчик будто в отпуске.

Причины:

Самое частое: обработчик не был правильно навешан. Например, вы пытаетесь найти элемент, которого ещё нет в DOM, или промахнулись с селектором.


// Пример: элемент ещё не создан на момент навешивания обработчика
const btn = document.getElementById('myBtn');
btn.addEventListener('click', function() {
  console.log('Кнопка нажата');
});

Если этот код стоит в <head> или до того, как <button id="myBtn"> появился в DOM, btn будет null — и никакой ошибки не будет, просто обработчик не навесится.

Решение:
Навешивайте обработчики после полной загрузки DOM. Например, в конце <body>, или внутри обработчика события DOMContentLoaded:


document.addEventListener('DOMContentLoaded', function() {
  const btn = document.getElementById('myBtn');
  btn.addEventListener('click', function() {
    console.log('Кнопка нажата');
  });
});

Ещё одна причина: Опечатка в селекторе или неверный id/класс.

2. Ошибка: обработчик срабатывает слишком много раз

Симптомы: В консоли появляется по 2, 3 или даже 10 сообщений вместо одного. При клике на кнопку что-то происходит несколько раз подряд.

Причины:

Чаще всего: обработчик навешивается в цикле или при каждом действии пользователя, а не один раз.


const btn = document.getElementById('myBtn');

function onClick() {
  console.log('Клик!');
}

// Ошибка: обработчик добавляется при каждом клике!
btn.addEventListener('click', function() {
  btn.addEventListener('click', onClick);
});

Или: обработчик не снимается после использования, если он должен был быть "одноразовым".

Решение:
Навешивайте обработчик один раз, вне других обработчиков и циклов. Если обработчик нужен только для одного раза — снимайте его вручную:


function onClickOnce(event) {
  console.log('Кнопка была нажата!');
  event.target.removeEventListener('click', onClickOnce);
}

btn.addEventListener('click', onClickOnce);

3. Ошибка: this внутри обработчика не тот, что ожидался

Симптомы: Внутри обработчика this — не элемент, а undefined или window. Вы хотите изменить стиль кнопки, а в обработчике this не работает.

Причины:

В стандартной функции:
В обработчике, навешанном через addEventListener, this указывает на элемент, на который навешан обработчик.


btn.addEventListener('click', function() {
  this.style.background = 'red'; // ок!
});

Но если вы используете стрелочную функцию:


btn.addEventListener('click', () => {
  this.style.background = 'red'; // this тут не про кнопку!
});

Стрелочные функции не имеют своего this!
Внутри стрелочной функции this берётся из внешнего контекста (например, из window или из модуля). Поэтому для обработчиков событий лучше использовать обычные function.

Решение:
Используйте обычные функции, если нужен this.
Или используйте event.target:


btn.addEventListener('click', (event) => {
  event.target.style.background = 'red';
});

4. Ошибка: обработчик навешивается на коллекцию, а не на элементы

Симптомы: Хотите навесить обработчик на все кнопки, но ничего не работает. В консоли: "addEventListener is not a function".

Причины:

Вы получили коллекцию элементов (NodeList или HTMLCollection), а не отдельный элемент, и пытаетесь навесить обработчик на всю коллекцию.


const buttons = document.getElementsByClassName('myBtn');
buttons.addEventListener('click', handler); // Ошибка!

Решение:
Перебирайте коллекцию и навешивайте обработчик на каждый элемент:


const buttons = document.querySelectorAll('.myBtn');
buttons.forEach((btn) => {
  btn.addEventListener('click', handler);
});

5. Ошибка: забыли снять обработчик — утечка памяти

Симптомы: После навигации или удаления элементов обработчики "висят" и продолжают работать. Приложение начинает "тормозить" после долгой работы.

Причины:

Если вы динамически создаёте и удаляете элементы или переходите между страницами (SPA), старые обработчики могут продолжать жить в памяти, если не были сняты.

Решение:
Снимайте обработчики при удалении элементов или перед их повторным созданием.


function handler() {
  // ...
}
btn.addEventListener('click', handler);
// ...
btn.removeEventListener('click', handler);

Важно:
removeEventListener работает только если вы передаёте ту же функцию, что и при навешивании! Анонимные функции не снимутся.

6. Ошибка: обработчик срабатывает на родителе, а не на дочернем элементе

Симптомы: Клик по дочернему элементу вызывает обработчик родителя. Нужно обработать клик только по конкретной кнопке, но срабатывает на всём контейнере.

Причины:

Это связано с "всплытием событий" (event bubbling) — событие поднимается вверх по DOM.

Решение:
Проверяйте, на каком элементе произошло событие, с помощью event.target.


container.addEventListener('click', function(event) {
  if (event.target.matches('button.special')) {
    // Только для кнопок с классом special
    doSomething();
  }
});

Если нужно остановить всплытие:


event.stopPropagation();

7. Ошибка: забыли event.preventDefault() — стандартное поведение браузера мешает

Симптомы: При сабмите формы страница перезагружается, хотя вы хотели сделать это через JS. Клик по ссылке уводит пользователя на другой адрес, хотя вы хотели обработать клик через JS.

Причины:

Стандартное поведение браузера не отменено.

Решение:
В обработчике вызвать event.preventDefault():


form.addEventListener('submit', function(event) {
  event.preventDefault();
  // ваша логика отправки формы через JS
});

8. Ошибка: неправильная работа с параметрами обработчика

Симптомы: Обработчик вызывается сам по себе, без события. В консоли ошибка: "Cannot read property 'target' of undefined".

Причины:

Вы случайно вызываете обработчик сразу, а не передаёте функцию.


btn.addEventListener('click', myHandler()); // Ошибка: myHandler вызовется сразу

Решение:
Передавайте саму функцию, а не результат её вызова:


btn.addEventListener('click', myHandler); // правильно

Если нужно передать параметры, используйте обёртку:


btn.addEventListener('click', function(event) {
  myHandler(event, 42);
});

9. Ошибка: обработчик не работает после динамического создания элемента

Симптомы: Добавили элемент через JS, но обработчик не срабатывает. Старые элементы работают, новые — нет.

Причины:

Обработчики навешиваются только на существующие в DOM элементы. Если элемент создан после навешивания, обработчик на нём не появится.

Решение:
Навешивайте обработчик сразу после создания элемента:


const btn = document.createElement('button');
btn.textContent = 'Кнопка';
btn.addEventListener('click', handler);
container.appendChild(btn);

Или используйте делегирование событий — навешивайте обработчик на родительский элемент.

10. Ошибка: смешение inline-обработчиков и addEventListener

Симптомы: В HTML: <button onclick="doSomething()">
В JS: button.addEventListener('click', doSomethingElse)
В итоге срабатывают оба обработчика, или только один, или что-то странное.

Причины:

Обработчики, навешанные через HTML (onclick="..."), и через JS (addEventListener) независимы друг от друга. Они могут срабатывать оба, порядок не всегда очевиден.

Решение:
Используйте только один подход! Рекомендуется использовать JS и addEventListener для отделения логики от разметки.

11. Ошибка: неправильное использование removeEventListener

Симптомы: Пытаетесь снять обработчик, но он не снимается. В консоли: обработчик продолжает срабатывать.

Причины:

removeEventListener работает только если вы передаёте ровно ту же функцию, что и при навешивании.


btn.addEventListener('click', function() {
  // ...
});
btn.removeEventListener('click', function() {
  // ...
}); // Не снимется! Это две разные функции

Решение:
Используйте именованные функции:


function handler() {
  // ...
}
btn.addEventListener('click', handler);
btn.removeEventListener('click', handler);

12. Ошибка: забыли про пассивные события при скролле

Симптомы: Скроллинг на мобильных устройствах "тормозит". В консоли предупреждение о том, что обработчик не пассивный.

Причины:

Для событий touchstart, touchmove, wheel рекомендуется явно указывать { passive: true }, если вы не используете event.preventDefault(). Это ускоряет скроллинг.

Решение:


window.addEventListener('scroll', handler, { passive: true });
1
Задача
Модуль 1: Web Core, 23 уровень, 4 лекция
Недоступна
Куки: имя пользователя
Куки: имя пользователя
1
Задача
Модуль 1: Web Core, 23 уровень, 4 лекция
Недоступна
Удаление куки
Удаление куки
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ