jQuery .on(); vs JavaScript .addEventListener();

When you use .on() at the document level, you're waiting for the event to bubble all the way up to that point. The event handler for any intermediate container will already have been called.

Event "bubbling" is the process by which the browser looks for event handlers registered with parents of the element that was the actual original recipient of the event. It works upwards in the DOM tree. The document level is the last level checked. Thus, your handler registered with .on() won't run until that level is reached. In the meantime, the other event handler at the "outer" level is reached first and it is executed by the browser.

Thus, that return false; in the handler registered with .on() is pretty much useless, as would be a call to event.stopPropagation(). Beyond that, mixing native event handler registration with the work that a library like jQuery will do is probably a really bad idea unless you seriously know what you're doing.

There was a question asked almost exactly like this one just a little while ago today.


Look at the addEventListener version:

document.getElementById('outer').addEventListener('mouseup', function (event) {
    alert('This alert should not show up!');
}, false);

That works fine because the third argument is useCapture, which specifies whether or not the capture phase of the event should be used.

When you switch to the jQuery version:

$('#outer').on('mouseup', function (event) {
    alert('This alert should not show up!');
}, false);

I think what is happening is the third argument simply overrides your event handler function and causes the event handler to do nothing but return false; which is clearly not what is meant to happen.

From the jQuery docs (emphasis added):

A function to execute when the event is triggered. The value false is also allowed as a shorthand for a function that simply does return false.

Remove the false argument and the jQuery version will work correctly too:

$('#outer').on('mouseup', function (event) {
    alert('This alert should not show up!');
});

Note that the alert should show up, so the addEventListener approach is working correctly. See @Pointy's answer for why that is.