Ты написал свою первую кнопку. Она красивая. У неё border-radius. У неё hover-эффект. Ты даже тень добавил. Она идеальна.
Ты нажимаешь… Ничего. Ещё раз. Ничего.
Ты открываешь консоль. Там тишина. Ни ошибки, ни предупреждения. JavaScript молчит, как твой бывший.
Добро пожаловать в мир дебага. Давай разберём самые частые причины, почему кнопка отказывается работать.
БАГ 1.

Скрипт загрузился раньше DOM
Уровень боли: 🔥🔥🔥🔥🔥
Это классика. Тебя предупреждали, ты не слушал.
// script.js — подключён в <head>const btn = document.querySelector('.my-button');
btn.addEventListener('click', () => {
alert('Работает!');
});Когда этот код выполняется, кнопки ещё физически не существует в DOM. querySelector возвращает null. А null.addEventListener — это TypeError, просто ты не заметил, потому что не смотрел в консоль.
✅ Как чинить:
<!-- Вариант 1: defer --><script src="script.js" defer></script>
<!-- Вариант 2: скрипт перед </body> -->// Вариант 3: DOMContentLoaded
document.addEventListener('DOMContentLoaded', () => {
const btn = document.querySelector('.my-button');
btn.addEventListener('click', () => alert('Работает!'));
});Нельзя обнять того, кто ещё не родился. DOM должен быть готов.
БАГ 2.
Опечатка в селекторе
Уровень боли: 🔥🔥 (но стыда — на 🔥🔥🔥🔥🔥)
// В HTML: <button class="my-button">const btn = document.querySelector('.my-buton'); // один 't' 💀querySelector не кидает ошибку, если элемент не найден. Он просто тихо возвращает null. А ты сидишь и думаешь, что JavaScript сломался.
✅ Как искать:
const btn = document.querySelector('.my-buton');
console.log(btn); // null — ага, вот ты где, подлецЕсли что-то не работает — console.log всё подряд. Это не «грязный хак», это инструмент. Даже сеньоры так делают. Особенно сеньоры.
БАГ 3.
addEventListener с ошибкой
Уровень боли: 🔥🔥🔥
// Ты думаешь, что повесил обработчик:
btn.addeventlistener('click', handleClick);
// JS: "а что такое addeventlistener? не знаю такого"
// Правильно:
btn.addEventListener('click', handleClick);JavaScript — язык, чувствительный к регистру. addEventListener — именно так, с большими буквами E и L. Одна буква не в том регистре — и тебя игнорируют.
А ещё бывает: ты определил функцию, но забыл повесить обработчик. Функция есть, а addEventListener нигде нет. Код молчит.
БАГ 4.
Перекрытие элемента (z-index)
Уровень боли: 🔥🔥🔥🔥
Кнопка есть. Обработчик есть. Код правильный. Но клик не срабатывает.
Причина: поверх кнопки лежит прозрачный div. Может это оверлей модалки, который ты забыл убрать. Может абсолютно позиционированный блок с z-index: 9999. Может ::after-псевдоэлемент расползся.
✅ Как найти:
// Этот код покажет, на что РЕАЛЬНО попадает клик
document.addEventListener('click', (e) => {
console.log('Кликнуто по:', e.target);
});/* Если блокирующий элемент не нужен для кликов: */.overlay { pointer-events: none; }DevTools → правый клик → «Исследовать элемент». Если выделяется НЕ кнопка — вот он, виновник.
БАГ 5.
onclick перезаписывается
Уровень боли: 🔥🔥🔥
// ❌ onclick — это свойство. Новое значение = старое исчезло
btn.onclick = () => console.log('Первый');
btn.onclick = () => console.log('Второй');
// Сработает ТОЛЬКО второй!
// ✅ addEventListener ДОБАВЛЯЕТ, а не заменяет
btn.addEventListener('click', () => console.log('Первый'));
btn.addEventListener('click', () => console.log('Второй'));
// Сработают ОБА ✨onclick — как переменная: присвоил новое — старое пропало. addEventListener — как массив: добавляет, а не заменяет.
БАГ 6.
Вызываешь функцию вместо передачи ссылки
Уровень боли: 🔥🔥🔥🔥🔥 (потому что непонятно, что происходит)
Ловушка, в которую попадают все новички:
function sayHello() {
alert('Привет!');
}
// ❌ Функция вызывается СРАЗУ, а не по клику
btn.addEventListener('click', sayHello());
// ✅ Передаём ССЫЛКУ — JS вызовет потом
btn.addEventListener('click', sayHello);Разница — в скобках. sayHello() — «позвони маме прямо сейчас при всех». sayHello — «позвони маме, когда будет клик».
БАГ 7.
Кнопка внутри формы (preventDefault)
Уровень боли: 🔥🔥🔥🔥
<form><button>Отправить</button></form><!-- Нажимаешь — страница перезагружается 💀 --><button> внутри формы по умолчанию имеет type="submit". Форма отправляется, страница обновляется, твой console.log мелькает и исчезает.
✅ Как чинить:
<!-- Вариант 1: указать type --><button type="button">Не отправляй форму!</button>// Вариант 2: preventDefault
btn.addEventListener('click', (e) => {
e.preventDefault();
// теперь твоя логика
});А обратная ситуация: кто-то выше по DOM повесил stopPropagation(), и событие просто не долетает. Добро пожаловать в мир всплытия событий — это отдельный квест.
БАГ 8.
Динамический элемент — обработчик повешен до создания
Уровень боли: 🔥🔥🔥🔥
// Вешаешь обработчик
document.querySelector('.dynamic-btn').addEventListener('click', handler);
// Потом создаёшь кнопку через innerHTML
container.innerHTML = '<button class="dynamic-btn">Нажми</button>';
// Новая кнопка — ДРУГОЙ объект. Обработчик к ней не привязан.✅ Решение — делегирование событий:
// Вешаем обработчик на РОДИТЕЛЯ, который всегда существует
document.querySelector('.container').addEventListener('click', (e) => {
if (e.target.matches('.dynamic-btn')) {
handler();
}
});Делегирование событий — один из самых важных паттернов в JavaScript. Запомни его, полюби его, живи с ним.
📋 Чек-лист «кнопка не работает»
Перед тем как писать в Stack Overflow «ПОМОГИТЕ НИЧЕГО НЕ РАБОТАЕТ», пройди по списку:
Открыл консоль? — Если нет, открой. Прямо сейчас. F12.
Элемент существует? —
console.log(querySelector(...))не null?Скрипт после DOM? — defer / DOMContentLoaded / скрипт перед
</body>.Селектор правильный? — Проверь классы, id, опечатки.
addEventListener верный? — Регистр, скобки, всё на месте?
Передаёшь функцию? —
handlervshandler().Ничего не перекрывает? — DevTools → Inspect → что выделяется?
Элемент динамический? — Используй делегирование.
🚀 Хочешь прокачаться по-настоящему?
Разбирать баги — это весело (ну, почти). Но чтобы реально понимать, почему что-то ломается, нужно разобраться в основах: DOM, event loop, замыкания, this...
Попробуй Кодик — приложение, где можно изучать программирование через реальные задачи. Не «прочитай и забудь», а «напиши код → проверь результат». JavaScript, Python, HTML/CSS и другие языки с интерактивными заданиями.
А ещё заходи в наш Telegram-канал — разборы задач, мини-уроки, шпаргалки и мемы про разработку. Повторяй программирование в удобном месте — в очереди, в транспорте или «ещё 5 минут перед сном».
Финальная мудрость
90% «сложных багов» — это опечатки, неправильный порядок загрузки и невнимательность. Звучит обидно, но это хорошая новость: чем больше ты дебажишь, тем быстрее находишь проблему.
Через полгода ты будешь видеть баги за 3 секунды.
А пока — открывай консоль. Всегда открывай консоль.
🐛 Happy debugging
