Facebook Pixel

Event Listeners in JavaScript: A Complete Guide

addEventListener registers callbacks for DOM events. Here is how it works, this binding, and cleanup.

Event Listeners in JavaScript: A Complete Guide

addEventListener registers a callback (event handler) that runs when a DOM event occurs. It is the standard way to handle user interaction.

Basic Usage

const button = document.querySelector("button"); button.addEventListener("click", (event) => { console.log("clicked", event.target); }); `` ### The Event Object The callback receives an `event` object with properties: - `event.target`: the element that triggered the event. - `event.currentTarget`: the element the listener is registered on. - `event.type`: the event type ("click", "input", etc.). - `event.preventDefault()`: prevents the default behavior. - `event.stopPropagation()`: stops the event from bubbling. ### Multiple Listeners ```js button.addEventListener("click", handler1); button.addEventListener("click", handler2); // both run on click (in registration order) `` ### Removing Listeners ```js const handler = () => console.log("clicked"); button.addEventListener("click", handler); // later: button.removeEventListener("click", handler); // must be the same reference `` Anonymous functions cannot be removed because you do not have a reference to them. ### Event Bubbling and Capturing Events bubble from the target up to the document. You can listen in the capturing phase (downward) with the third argument: ```js element.addEventListener("click", handler, true); // capturing phase element.addEventListener("click", handler, false); // bubbling phase (default) `` Stop bubbling with `event.stopPropagation()`. ### `this` in Event Handlers - **Regular function**: `this` is the element (`event.currentTarget`). - **Arrow function**: `this` is lexical (from the enclosing scope), not the element. ```js button.addEventListener("click", function () { console.log(this); // the button }); button.addEventListener("click", () => { console.log(this); // lexical this (not the button) console.log(event.currentTarget); // use this instead }); `` ### Event Delegation Instead of adding a listener to each child, add one to the parent: ```js document.querySelector("#list").addEventListener("click", (event) => { if (event.target.tagName === "LI") { console.log("clicked", event.target.textContent); } }); `` This works for dynamically added children too. ### Common Event Types - Mouse: `click`, `dblclick`, `mousedown`, `mouseup`, `mousemove`, `mouseenter`, `mouseleave`. - Keyboard: `keydown`, `keyup`, `keypress` (deprecated). - Form: `input`, `change`, `submit`, `focus`, `blur`. - Window: `resize`, `scroll`, `load`, `DOMContentLoaded`. ### Memory and Cleanup Always remove listeners when elements are removed (especially in SPAs): ```js // React useEffect(() => { const handler = () => { ... }; window.addEventListener("resize", handler); return () => window.removeEventListener("resize", handler); }, []); `` ### The Takeaway `addEventListener` registers callbacks for DOM events. The callback receives an event object. Regular functions get `this` as the element; arrows get lexical `this` (use `event.currentTarget`). Use named functions for removable listeners. Use event delegation for dynamic children. Always clean up listeners to avoid memory leaks.

It registers a callback (event handler) on an element. When the specified event occurs, the callback is called with an event object containing target, currentTarget, type, and methods like preventDefault and stopPropagation.

Use removeEventListener with the same event type and the same function reference. Anonymous functions cannot be removed because you do not have a reference. Store the handler in a variable first.

In a regular function handler, this is the element (event.currentTarget). In an arrow function handler, this is lexical (from the enclosing scope), not the element. Use event.currentTarget to get the element in arrow handlers.

Instead of adding a listener to each child element, add one listener to the parent. Use event.target to determine which child was clicked. This works for dynamically added children and is more memory-efficient.

Events propagate from the target element up to the document. A click on a button inside a div inside body triggers listeners on the button, then the div, then the body. Stop it with event.stopPropagation(). Listen in the downward (capturing) phase with addEventListener(type, fn, true).

Ready to master React completely?

Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.

Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.