What are event listeners and how are they used?
TL;DR
Event listeners register callbacks on an EventTarget for events such as clicks, input, network state, or custom notifications. addEventListener() supports options for capture, one-time delivery, passive scrolling behavior, and cleanup through an AbortSignal. Keep ownership explicit: remove long-lived listeners when their feature is disposed, and use event delegation when many dynamic descendants share behavior.
document.getElementById('myButton').addEventListener('click', function () {alert('Button was clicked!');});
What are event listeners and how are they used?
Event listeners are a fundamental part of web development, allowing developers to make web pages interactive by responding to user actions. They are functions that wait for specific events to occur on elements, such as clicks, key presses, or mouse movements, and then execute a specified function when those events occur.
Adding an event listener
To add an event listener to an element, you use the addEventListener method. This method takes two main arguments: the type of event to listen for and the function to execute when the event occurs.
const button = document.getElementById('myButton');button.addEventListener('click', function () {alert('Button was clicked!');});
In this example, an event listener is added to a button element with the ID myButton. When the button is clicked, an alert box will appear with the message "Button was clicked!".
Removing an event listener
You can also remove an event listener using the removeEventListener method. This method requires the same arguments as addEventListener: the event type and the function to remove.
function handleClick() {alert('Button was clicked!');}button.addEventListener('click', handleClick);// Later, you can remove the event listenerbutton.removeEventListener('click', handleClick);
removeEventListener() needs the same event type, callback identity, and capture setting. An inline function cannot be removed later by writing a new identical-looking function. An AbortController can own several listeners:
const controller = new AbortController();window.addEventListener('resize', handleResize, {signal: controller.signal,});document.addEventListener('visibilitychange', handleVisibility, {signal: controller.signal,});// Disposes both listeners.controller.abort();
Event object
When an event listener is triggered, an event object is passed to the event handler function. This object contains useful information about the event, such as the target element, the type of event, and more.
button.addEventListener('click', function (event) {console.log('Event type:', event.type);console.log('Target element:', event.target);});
Common event types
click: Triggered when an element is clickedmouseover: Triggered when the mouse pointer is moved over an elementmouseout: Triggered when the mouse pointer is moved out of an elementkeydown: Triggered when a key is pressed downkeyup: Triggered when a key is released
Event delegation
Event delegation is a technique where a single event listener is added to a parent element to manage events for multiple child elements. This is useful for improving performance and managing dynamic content.
const list = document.getElementById('myList');list.addEventListener('click', function (event) {if (event.target && event.target.nodeName === 'LI') {console.log('List item clicked:', event.target.textContent);}});
In this example, a single event listener is added to a list element. When any list item (LI) is clicked, the event listener will handle the event.
Use event.target.closest('li') in real delegated handlers so clicks on a nested element still resolve to the list item, and verify the matched item belongs to the intended list. Delegation reduces listener management; it is not automatically faster for every small, fixed interface.
Listener options and failure modes
{ once: true }removes a listener after its first invocation.{ passive: true }promises not to callpreventDefault(), allowing the browser to optimize relevant scrolling events. CallingpreventDefault()from that listener has no effect.{ capture: true }listens during capture instead of the normal bubbling phase.- A listener runs on the event loop's thread. CPU-heavy handlers still block rendering and input.
- A thrown error does not turn
dispatchEvent()into a rejected Promise. Handle asynchronous work and errors explicitly.
Further reading
- MDN Web Docs: EventTarget.addEventListener()
- MDN Web Docs: EventTarget.removeEventListener()
- JavaScript.info: Introduction to browser events
- MDN Web Docs: Introduction to events