How do event listeners work in JavaScript?
You register a function against a type of event on a target, and the browser calls it when that event happens on that target. The addEventListener method takes the event type as a string, the function to call, and an optional options object.
// Node ships the same EventTarget API the browser uses, so this runs here too.
const button = new EventTarget();
let clicks = 0;
const onClick = (event) => {
clicks += 1;
console.log("clicked", clicks, "type:", event.type);
};
button.addEventListener("click", onClick);
button.dispatchEvent(new Event("click"));
button.dispatchEvent(new Event("click"));
console.log("total clicks:", clicks); // 2The important detail is the options object, because it controls how the listener behaves. The capture option decides which phase of the event propagation the listener runs in, and it defaults to false, meaning the bubble phase. The once option removes the listener after it fires for the first time. The passive option promises that the listener will not call preventDefault, which lets the browser keep scrolling smoothly even while the listener runs.
Listeners fire in the order they were added, and the same function can be registered for the same event more than once, in which case it runs once per registration. That last point is the source of a very common bug, where a component that re-registers its listener on every render ends up handling a single click several times.
There is also the older approach of assigning a handler property, such as element.onclick. It is simpler, but it replaces any previous handler rather than adding to it, and it does not support the capture, once or passive options. New code should use addEventListener.