Event Binding
addEventListener and the onevent property both wire functions to events, but only one of them lets you attach multiple handlers. Knowing the difference changes how you structure event-driven code.
Every interactive piece of a web app runs because something listened for an event and responded. The DOM gives you two ways to set that up, and they are not equivalent.
The Essentials
- Events are everywhere: Click, double-click, change, keydown, scroll, focus, touch, pointer, drag, and many more. Any DOM element can have listeners for any applicable event.
- Special events live on window:
DOMContentLoadedandpopstatefire only onwindow. Listening for them on other elements will not work. - Naming pattern: Event names are lowercase, no word separator, no "ed" suffix. It is
clicknotclicked,changenotchanged.DOMContentLoadedis a historic exception. - onevent properties (
onclick,onchange): Each is a single-slot property. Assigning a second function overwrites the first. - addEventListener: Accepts multiple listeners for the same event on the same element. All of them fire in sequence.
A Taxonomy of Events
The DOM API ships with a large set of built-in events, and the W3C keeps adding more as new browser capabilities are standardized.
The most common ones:
| Category | Events |
|---|---|
| Pointer | click, dblclick, mousedown, mouseup, mousemove |
| Keyboard | keydown, keyup, keypress |
| Form | change, input, submit, focus, blur |
| Document | DOMContentLoaded, load |
| History | popstate |
| Scroll | scroll |
| Touch | touchstart, touchend, touchmove |
| Drag | dragstart, drag, drop, dragover |
Some of these belong to newer W3C specs layered on top of the core DOM: the Pointer Events API, the Touch Events API, the Drag and Drop API. They all follow the same addEventListener pattern.
The naming convention is strict: lowercase, no hyphens, no underscores, no -ed suffix at the end. You subscribe to click, not clicked. To change, not changed. The historical outlier is DOMContentLoaded, which mixes cases because it was defined before the naming convention was established.
onevent vs addEventListener
There are two mechanisms for wiring a function to an event.
onevent properties
Every DOM element has a set of onevent properties: onclick, onchange, onkeydown, and so on. These are simple properties. You assign a function to them:
button.onclick = () => console.log('clicked');The limitation: it is a property setter. Assign a second function to the same property and the first is gone:
button.onclick = () => console.log('first handler');
button.onclick = () => console.log('second handler'); // first one is lostJSX uses this same mental model, but with camelCase: onClick, onChange, onSubmit. The naming is different but the one-handler-per-event structure is the same.
addEventListener
addEventListener uses the observer pattern. You register handlers, and all of them fire when the event occurs:
button.addEventListener('click', () => console.log('first handler'));
button.addEventListener('click', () => console.log('second handler'));
// Both fire when the button is clickedYou can separate concerns without worrying about overwriting another module's handler. Each part of the code subscribes independently. This is why addEventListener is the standard choice for anything beyond the simplest examples.
Note that native DOM event names go in as lowercase strings: 'click', 'change', 'keydown'. Not 'onClick' or 'onChange'. The camelCase convention is JSX-specific.
Separating Initialization Concerns
One practical advantage of addEventListener: you can call it multiple times on the same event without conflict. This lets you split initialization logic across files:
// In router.js
window.addEventListener('DOMContentLoaded', initRouter);
// In menu.js
window.addEventListener('DOMContentLoaded', initMenu);
// Both run when the DOM is ready, in the order they were registeredWithout addEventListener, only one of these could exist. With it, each module subscribes to the events it cares about without needing to know what other modules have registered.
Further Reading and Watching
- MDN: addEventListener - Full reference including event options and the difference from
onevent. - MDN: Event reference - Complete list of standard DOM events organized by category.
Video:
- JavaScript DOM Crash Course - Part 3 by Traversy Media. Covers event handling,
addEventListener, and event delegation.