Потому что так работает обработка событий. События сначала проходят фазу capture из окна через документ к целевому элементу, а затем bubble из целевого элемента в окно.
Ваш первый вызов on
присоединяет обработчик click
к document
, который при вызове проверяет, прошло ли событие какие-либо элементы, соответствующие .myClass
между конечной целью и document
, и, если Итак, вызывает ваш обработчик. Ваш второй вызов on
присоединяет обработчик непосредственно к соответствующему элементу (ам). В обоих случаях вы подключаете фазу пузырьков (jQuery не поддерживает подключение фазы захвата). Таким образом, обработчик самого элемента вызывается перед соответствующим делегированным хандером в документе. (Технически, когда событие в целевом элементе, оно находится в фазе target , не в захвате и не в пузырях. Но и обработчики захвата, и пузырьки обрабатываются & mdash; и в этом порядке & mdash ; на целевом элементе.)
Вот отличная диаграмма "все в одном" из старой спецификации DOM3 Events :
![enter image description here](https://i.stack.imgur.com/H6r8J.png)
Подробности можно найти в текущей спецификации DOM4 .
Хотя jQuery не поддерживает фазу захвата, addEventListener
поддерживает совместимые браузеры (то есть не IE8 и более ранние, которые не имели захвата или addEventListener
). Третий аргумент addEventListener
позволяет вам решить, хотите ли вы захватить (true
) или всплыть (false
); по умолчанию false
(в действительно современных системах третьим аргументом может быть объект с различными флагами).
Вот пример, показывающий событие на всех его этапах:
// See: https://www.w3.org/TR/domcore/#dom-event-none
const eventPhases = ["NONE", "CAPTURING_PHASE", "AT_TARGET", "BUBBLING_PHASE"];
function captureHandler(e) {
console.log("captureHandler: " + eventPhases[e.eventPhase] + " on " + this.id);
}
function bubbleHandler(e) {
console.log("bubbleHandler: " + eventPhases[e.eventPhase] + " on " + this.id);
}
function hookBoth(element) {
element.addEventListener("click", captureHandler, true);
element.addEventListener("click", bubbleHandler, false);
}
hookBoth(document.getElementById("outer"));
hookBoth(document.getElementById("middle"));
hookBoth(document.getElementById("target"));
<div id="outer">
<div id="middle">
<div id="target">Click Me</div>
</div>
</div>