События в 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, текст звонка и слово на кнопке.
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.
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. После щелчка в ячейке по-прежнему функция.
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.
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.
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. Текст кнопки она не пишет.
<!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.
Пять проверок
- Прочитай
onclick,typeof bell.onclick, текст звонка и текст кнопки. Значения: null, object, silent и press. - Назначь функцию ding и не щёлкай.
typeofравен function, звонок silent, иonclick === nullравен false. - Вызови
bell.click()с этой функцией ding. Звонок ding, кнопка press,typeofравен function. - Назначь ding, потом dong, потом один щелчок.
onclick === dingравен false,onclick === dongравен true, звонок dong. - На свежей кнопке назначь функцию, поставь
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
🧠 Проверьте Свои Знания
Проверьте Свои Знания
Бросьте себе вызов с помощью этой интерактивной викторины и узнайте, насколько хорошо вы понимаете тему
📝 Инструкции
- Внимательно прочитайте каждый вопрос
- Выберите лучший ответ на каждый вопрос
- Вы можете пересдавать тест столько раз, сколько захотите
- Ваш прогресс будет показан вверху