Загрузка...

Объект события

На стене музея одна табличка. Внешний ящик — #wall. Внутри #plaque держит ссылку #seal. На ссылке слово open, а href равен /wing. Под стеной #slip говорит blank.
Браузер передаёт функции один объект. Параметр зовут event. event.type — вид события. Клик ставит эту строку в click. event.target — элемент, на который сел клик. event.currentTarget — элемент, на котором сидит этот слушатель. Они совпадают, только если клик и слушатель на одном элементе.
Печать — ссылка. preventDefault отменяет переход на /wing. После вызова event.defaultPrevented равен true. Без вызова флаг остаётся false. Дальше клик идёт наружу: печать, табличка, стена. stopPropagation на табличке обрывает путь, слушатель стены не выполняется.
Скрипт страницы щёлкает печать один раз. Строка под табличкой: click / seal / plaque / true / quiet. Здесь не пишут onclick, не вызывают removeEventListener и не создают элемент.

Объект, который передаёт браузер

Прошлая страница была вешалка. У wool и silk не было параметра, они не читали этот объект. Их строка была wool silk / 2 / peg. Страница звонка записывала onclick и читала this. Эта страница так не делает. getElementById даёт только стену, табличку, печать и лист.
addEventListener по-прежнему только хранит функцию. Объект приходит, когда клик выполняет функцию, а не в момент добавления. currentTarget читай внутри функции. После возврата это свойство равно null.

Что сообщает один клик

Лист начинается с blank. Текст ссылки остаётся open. Читай строки по порядку. Каждый фрагмент начинается с этой свежей стены, кроме строки страницы: это демо внизу. Демо не вызывает removeEventListener.

📊 Что сообщает один клик

Момент Что читаешь Текст листа Легко перепутать
слушатель на печати, seal.click(), чтение типа event.type click читать id как тип
слушатель на табличке, клик по печати, target event.target.id seal читать currentTarget
тот же клик, currentTarget event.currentTarget.id plaque читать target
preventDefault на печати, затем флаг event.defaultPrevented true думать, что ссылка всё ещё уходит
без preventDefault event.defaultPrevented false думать, что каждый слушатель отменяет ссылку
stopPropagation на табличке, стена тоже слушает склейка marks plaque ждать plaque wall
скрипт страницы, один click строка click / seal / plaque / true / quiet строка кончается на wall

Клик по печати — один объект. Все слушатели на пути видят его. type не меняется. target не меняется. currentTarget меняется: это элемент, чей слушатель сейчас выполняется.
preventDefault говорит со стандартным действием браузера. У этой ссылки действие — переход на /wing. Вызов не снимает слушателя со списка. stopPropagation говорит с путём. Ссылку он не отменяет. Вызов одного — не вызов другого.
join(" ") ставит пробел только между словами, которые уже лежат в marks. Пустой список здесь не склеивают. Лист начинается со слова blank и меняется только внутри слушателя или в скрипте страницы после клика.

Тип

Слушатель сидит на печати. Функция называет параметр event и пишет event.type на лист. Затем выполняется seal.click().

Прочитать тип

javascript
let seal = document.getElementById("seal");
let slip = document.getElementById("slip");
function readType(event) {
slip.textContent = event.type;
}
seal.addEventListener("click", readType);
seal.click();
console.log(slip.textContent);

Вывод — click. Тип — это вид события, не id и не слово open.

Элемент под кликом

Свежая стена. Слушатель на табличке, не на печати. Клик всё равно садится на печать. event.target — этот элемент, значит event.target.id равен seal.

Прочитать target

javascript
let plaque = document.getElementById("plaque");
let seal = document.getElementById("seal");
let slip = document.getElementById("slip");
function readTarget(event) {
slip.textContent = event.target.id;
}
plaque.addEventListener("click", readTarget);
seal.click();
console.log(slip.textContent);

Вывод — seal. Элемент слушателя — табличка. target табличку не называет. Он называет элемент под кликом.

Где сидит слушатель

Та же свежая стена, слушатель всё ещё на табличке, клик всё ещё по печати. Лист пишет оба id: сначала target, потом currentTarget.

Прочитать оба id

javascript
let plaque = document.getElementById("plaque");
let seal = document.getElementById("seal");
let slip = document.getElementById("slip");
function readWhere(event) {
slip.textContent = event.target.id + " " + event.currentTarget.id;
}
plaque.addEventListener("click", readWhere);
seal.click();
console.log(slip.textContent);

Вывод — seal plaque. Первое слово — клик. Второе — элемент, которому принадлежит этот слушатель. Повесь слушатель на печать и кликни печать: оба id будут seal, потому что клик и слушатель на одном элементе. Это чтение идёт с таблички, поэтому id разные. currentTarget читай внутри функции. После возврата он null.

Отменить ссылку

href печати — /wing. Стандартное действие этого клика — перейти по ссылке. preventDefault отменяет это действие. Слушателя он не снимает. Сразу после вызова event.defaultPrevented равен true.

Отменить ссылку

javascript
let seal = document.getElementById("seal");
let slip = document.getElementById("slip");
function hold(event) {
event.preventDefault();
slip.textContent = String(event.defaultPrevented);
}
seal.addEventListener("click", hold);
seal.click();
console.log(slip.textContent);

Вывод — true. Без preventDefault то же чтение даёт false. Лист скажет false, и действие ссылки останется. stopPropagation этот флаг не ставит.

Клик идёт наружу

Печать внутри таблички, табличка внутри стены. Клик по печати доходит до слушателя таблички, затем до слушателя стены, если путь не оборван. stopPropagation на табличке обрывает его. Функция стены не выполняется. preventDefault путь не обрывает.

Оборвать путь

javascript
let wall = document.getElementById("wall");
let plaque = document.getElementById("plaque");
let seal = document.getElementById("seal");
let slip = document.getElementById("slip");
let marks = [];
function onPlaque(event) {
marks.push("plaque");
event.stopPropagation();
}
function onWall() {
marks.push("wall");
}
plaque.addEventListener("click", onPlaque);
wall.addEventListener("click", onWall);
seal.click();
slip.textContent = marks.join(" ");
console.log(slip.textContent);

Вывод — plaque. Слово wall в marks не попадает. Без stopPropagation тот же клик записал бы plaque wall. Демо внизу и обрывает путь, и отменяет ссылку.

Одна строка под табличкой

Скрипт стоит в конце body, когда стена и абзацы уже есть. Слушатель печати вызывает preventDefault. Слушатель таблички вызывает stopPropagation и запоминает тип, id у target, id у currentTarget и флаг. Слушатель стены поставил бы heard в wall, но путь уже оборван, поэтому heard остаётся quiet. Строка пишется после seal.click(), когда у стены был шанс.

Демо страницы — музейная табличка

html
<!DOCTYPE html>
<html>
<head>
<title>event-object — page</title>
</head>
<body>
<div id="wall">
<div id="plaque">
<a id="seal" href="/wing">open</a>
</div>
</div>
<p id="slip">blank</p>
<p id="line">…</p>
<script>
let wall = document.getElementById("wall");
let plaque = document.getElementById("plaque");
let seal = document.getElementById("seal");
let slip = document.getElementById("slip");
let kind = "";
let from = "";
let on = "";
let held = "";
let heard = "quiet";
seal.addEventListener("click", function (event) {
event.preventDefault();
});
plaque.addEventListener("click", function (event) {
event.stopPropagation();
kind = event.type;
from = event.target.id;
on = event.currentTarget.id;
held = String(event.defaultPrevented);
});
wall.addEventListener("click", function () {
heard = "wall";
});
seal.click();
slip.textContent = kind + " " + from + " " + on;
document.getElementById("line").textContent =
kind + " / " + from + " / " + on + " / " + held + " / " + heard;
</script>
</body>
</html>

Строка читается click / seal / plaque / true / quiet. Тип — click. id у target — seal. id у currentTarget — plaque, потому что этот слушатель на табличке. Флаг true, потому что слушатель печати вызвал preventDefault раньше, чем табличка прочитала флаг. Последнее слово quiet, не wall, потому что stopPropagation сработал на табличке. Текст open в строку не входит. Лист становится click seal plaque. Следующая страница — делегирование. Печать уже есть в разметке. Здесь после слушателя ребёнка не добавляют.

Пять проверок у таблички

  1. Повесь слушатель на печать и кликни. Лист — click.
  2. Повесь слушатель на табличку, кликни печать и прочитай event.target.id. Лист — seal.
  3. Тот же слушатель пишет оба id. Лист — seal plaque. Слушатель на самой печати написал бы seal seal.
  4. Вызови preventDefault и прочитай event.defaultPrevented. Лист — true. Без вызова — false.
  5. Вызови stopPropagation на табличке, стена тоже слушает. marks склеивается в plaque. Прочитай строку: click / seal / plaque / true / quiet.

Где эта табличка обманывает

На ссылке по-прежнему open. Лист — не текст ссылки.

  • Ждать, что аргумент функции — элемент печати, а не объект события
  • Читать event.target, когда нужен элемент слушателя
  • Читать event.currentTarget, когда нужен элемент под кликом
  • Ждать, что preventDefault снимет слушателя, как removeEventListener на вешалке
  • Ждать, что stopPropagation отменит переход на /wing
  • Ждать, что слушатель стены выполнится после stopPropagation на табличке
  • Читать event.currentTarget после возврата функции и ждать plaque
  • Писать onclick или читать this и typeof null; это была страница звонка
  • Собирать ссылку через createElement; это была более ранняя страница
  • Читать строку так, будто она кончается на wall, или как wool silk / 2 / peg

Что остаётся

  • После клика event.type равен click
  • Слушатель на табличке и клик по печати: event.target.id равен seal
  • На том же клике event.currentTarget.id равен plaque
  • Слушатель на печати: target и currentTarget оба равны seal
  • preventDefault делает event.defaultPrevented равным true, без вызова остаётся false
  • stopPropagation на табличке не даёт выполниться слушателю стены
  • Строка страницы: click / seal / plaque / true / quiet

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

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

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

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

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

📝 Инструкции

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