Загрузка...

События в JavaScript

У двери квартиры одна кнопка звонка. Кнопка — #bell, на ней написано press. Под ней #chime всё ещё говорит silent. В HTML нет атрибута onclick, поэтому bell.onclick с самого начала равен null.
Старая ловушка: typeof null в JavaScript даёт "object". Значит, typeof bell.onclick тоже "object", не "null" и не "undefined". Сравнение bell.onclick === null истинно.
Положить функцию в onclick — ещё не позвонить. Текст остаётся silent, пока bell.click() не выполнит функцию, которая сидит в ячейке. В ячейке место только для одной. Назначишь вторую — первая уходит. Один щелчок не запускает обе. addEventListener — следующая страница; там слушатели складываются стопкой. Здесь его не вызывают.
bell.onclick = null очищает ячейку. Щелчок после этого текст не трогает. Внутри функции this — сама кнопка, поэтому this.id равен bell. Слово на кнопке остаётся press. Скрипт страницы щёлкает один раз. Строка под звонком: dong / 1 / bell. Элемент здесь не создаётся, свойство CSS не задаётся.

Одна ячейка на кнопке

Прошлая страница собирала узлы li через createElement и ставила их через append, prepend и insertBefore. Здесь узел не создаётся и children не читается. Страница до той писала style и classList на образце краски. Здесь style не назначается. getElementById отдаёт только кнопку и абзац. Новое — свойство onclick: одна функция или null.

Что лежит в ячейке

Кнопка начинается с press, под ней silent. Читай строки по порядку. Каждый фрагмент стартует с этой свежей кнопки, кроме строки страницы — это демо внизу. Демо не ставит null.

📊 Что лежит в ячейке

Момент Что в onclick Текст звонка Легко перепутать
до любого назначения null; typeof равен "object" silent прочитать typeof как "null"
после функции ding, до click функция silent решить, что само назначение уже звонит
после click с ding эта функция ding текст кнопки становится ding
dong заменяет ding, затем один click функция dong, не ding dong обе функции выполняются
onclick = null, затем click, свежая кнопка null; typeof равен "object" silent пустая ячейка всё ещё звонит
скрипт страницы, один click функция; this.id равен bell dong строка кончается на silent

onclick — свойство элемента. Без обработчика значение равно null, а typeof null по-прежнему "object". Чтобы увидеть пустую ячейку, сравнивай через === null. Назначение только хранит функцию. Оно её не вызывает. bell.click() шлёт щелчок и выполняет ту функцию, которая в этот момент в ячейке. Собственный текст кнопки не меняется. Второе назначение переписывает свойство. Если у первой функции осталось имя, объект ещё в памяти, но свойство на него уже не указывает. onclick = null снимает обработчик. Атрибут HTML onclick заполнил бы ту же ячейку; у этой кнопки его нет. Стрелочная функция в этой ячейке не делает this кнопкой. На странице обычная function.

Ячейка сначала пуста

Файл открывается кнопкой и абзацем. Ещё ничего не назначено. Эти четыре вывода спрашивают свойство, его typeof, текст звонка и слово на кнопке.

Тихий звонок

javascript
let bell = document.getElementById("bell");
let chime = document.getElementById("chime");
console.log(bell.onclick);
console.log(typeof bell.onclick);
console.log(chime.textContent);
console.log(bell.textContent);

Выводы: null, object, silent и press. Ячейка пуста. typeof не печатает слово null. Кнопка и абзац всё ещё показывают слова из разметки.

Функция ждёт

onclick = function ... сохраняет функцию. Тело на этой строке не выполняется. Звонок всё ещё silent, и свойство уже не null.

Назначить, не звонить

javascript
let bell = document.getElementById("bell");
let chime = document.getElementById("chime");
bell.onclick = function () {
chime.textContent = "ding";
};
console.log(typeof bell.onclick);
console.log(chime.textContent);
console.log(bell.onclick === null);

Выводы: function, silent и false. В ячейке видна функция. Абзац не изменился, потому что функцию никто не вызвал.

click выполняет ту, что в ячейке

bell.click() выполняет текущий обработчик. Звонок становится ding. Текст кнопки остаётся press. После щелчка в ячейке по-прежнему функция.

Один щелчок

javascript
let bell = document.getElementById("bell");
let chime = document.getElementById("chime");
bell.onclick = function () {
chime.textContent = "ding";
};
bell.click();
console.log(chime.textContent);
console.log(bell.textContent);
console.log(typeof bell.onclick);

Выводы: ding, press и function. Один щелчок, одно изменение, и оно в абзаце. Слово press всё ещё на кнопке.

Вторая функция заменяет первую

Этот фрагмент снова начинается со свежей кнопки. Сначала сохраняется ding, потом поверх пишется dong, и только затем один click. Между назначениями щелчка нет, поэтому в этом прогоне звонок никогда не становится ding. После щелчка он dong. bell.onclick === ding равен false. bell.onclick === dong равен true.

Остаётся вторая

javascript
let bell = document.getElementById("bell");
let chime = document.getElementById("chime");
function ding() {
chime.textContent = "ding";
}
function dong() {
chime.textContent = "dong";
}
bell.onclick = ding;
bell.onclick = dong;
bell.click();
console.log(bell.onclick === ding);
console.log(bell.onclick === dong);
console.log(chime.textContent);

Выводы: false, true и dong. Имя ding всё ещё указывает на функцию. Свойство — нет. Один щелчок выполнил только dong.

null очищает ячейку

Запусти это на свежей кнопке. Функцию назначают и стирают до любого щелчка. bell.click() после null не пишет dong. Звонок остаётся silent. typeof снова object, потому что значение — null.

Очистить ячейку

javascript
let bell = document.getElementById("bell");
let chime = document.getElementById("chime");
bell.onclick = function () {
chime.textContent = "dong";
};
bell.onclick = null;
bell.click();
console.log(bell.onclick);
console.log(typeof bell.onclick);
console.log(chime.textContent);

Выводы: null, object и silent. Функции, которая написала бы dong, в момент щелчка в ячейке нет. Демо страницы ниже ячейку не очищает.

Строка под звонком

Скрипт стоит в конце body, после кнопки и абзаца. Он сохраняет одну функцию и один раз вызывает click. Внутри функции taps идёт от 0 к 1, звонок становится dong, а this.id пишется в bell.dataset.who. Строка склеивает текст звонка, счёт и этот id. Текст кнопки она не пишет.

Демо страницы — дверной звонок

html
<!DOCTYPE html>
<html>
<head>
<title>events — page</title>
</head>
<body>
<button id="bell" type="button">press</button>
<p id="chime">silent</p>
<p id="line">…</p>
<script>
let bell = document.getElementById("bell");
let chime = document.getElementById("chime");
let taps = 0;
bell.onclick = function () {
taps = taps + 1;
chime.textContent = "dong";
bell.dataset.who = this.id;
};
bell.click();
document.getElementById("line").textContent =
chime.textContent + " / " + taps + " / " + bell.dataset.who;
</script>
</body>
</html>

Строка читается dong / 1 / bell. Звонок — dong, не silent. Число 1, потому что скрипт щёлкает один раз. Последний кусок — id кнопки, из this внутри обработчика, не слово press. На кнопке по-прежнему press. Следующая страница — про слушатели событий. Её главный инструмент — не эта одна ячейка onclick.

Пять проверок

  1. Прочитай onclick, typeof bell.onclick, текст звонка и текст кнопки. Значения: null, object, silent и press.
  2. Назначь функцию ding и не щёлкай. typeof равен function, звонок silent, и onclick === null равен false.
  3. Вызови bell.click() с этой функцией ding. Звонок ding, кнопка press, typeof равен function.
  4. Назначь ding, потом dong, потом один щелчок. onclick === ding равен false, onclick === dong равен true, звонок dong.
  5. На свежей кнопке назначь функцию, поставь onclick в null и щёлкни. Значения: null, object и silent. Строка страницы: dong / 1 / bell.

Где этот звонок обманывает

На кнопке всё ещё press. В ячейке была не та функция, или ячейка была пуста.

  • Читать typeof bell.onclick как "null", когда значение null
  • Ждать, что само назначение сменит звонок на ding
  • Ждать, что после второго назначения один щелчок запустит и ding, и dong
  • Ждать, что текст кнопки станет ding
  • Ждать, что click изменит звонок после onclick = null
  • Взять стрелочную функцию и ждать, что this.id равен bell
  • Читать здесь event.target; у этих функций нет аргумента, объект события — на более поздней странице
  • Вызывать здесь addEventListener; следующая страница складывает слушатели
  • Собирать кнопку через createElement; это была прошлая страница
  • Читать строку как silent / 0 / press

Что уносишь с собой

  • Без обработчика bell.onclick равен null, а typeof bell.onclick равен object
  • Назначение функции оставляет звонок silent до click
  • bell.click() с функцией ding ставит звонок в ding и оставляет кнопку press
  • Второе назначение заменяет первое, поэтому один щелчок выполняет только dong
  • onclick = null и затем click на свежей кнопке оставляют звонок silent
  • Строка страницы — dong / 1 / bell, и this.id внутри обработчика равен bell

🧠 Проверьте Свои Знания

Готов к Началу

Проверьте Свои Знания

Бросьте себе вызов с помощью этой интерактивной викторины и узнайте, насколько хорошо вы понимаете тему

❓
8
Вопросы
🎯
70%
Для Прохождения
♾️
∞
Время
🔄
∞
Попытки

📝 Инструкции

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