ReviseAlgo Logo

DOM Manipulation

Event Delegation

Master event delegation in JavaScript. Learn to manage events using a single parent handler, reduce memory usage, and handle dynamic list elements.

Last Updated: July 15, 2026 10 min read

1. Introduction

Attaching event listeners to hundreds of child elements consumes a lot of memory. Event Delegation is a pattern that solves this by attaching a single event listener to a parent container, using event bubbling to capture and process events from child elements.

2. Why It Matters

In dynamic lists where elements are constantly added or removed, managing separate event listeners is difficult and can cause memory leaks. Event delegation simplifies event handling by automatically capturing events on new elements without needing to register new listeners.

3. Real-World Analogy

Think of an Office Mailroom:

  • Individual Listeners: Hiring 100 delivery messengers, one for every desk in the building. When a package arrives for a desk, its assigned messenger delivers it. This requires keeping 100 employees on the payroll (high memory consumption).
  • Event Delegation (Central Mailroom Clerk): Hiring a single mailroom clerk at the entrance desk. All packages bubble through the front desk. The clerk reads the label on each package (inspects the target element) and forwards it to the correct desk. You only need a single clerk to manage deliveries for the entire building.

4. How It Works

Because events bubble up the DOM, clicking a child element triggers the click handler on its parent. Inside the parent listener, you can inspect event.target to identify which child element was clicked and determine the action:

5. The Closest() Match Pattern

Using event.target.matches('.selector') works only if the user clicks the element directly. If the element contains nested children (like an icon inside a button), event.target will reference the icon. Using event.target.closest('.selector') resolves this issue by searching up the DOM tree to find the matching element.

6. Practical Example

This script demonstrates using event delegation to handle clicks on tabs in a menu dynamically:

7. Common Mistakes

  • Not filtering target elements: Forgetting to verify that event.target is a match before executing logic. This can cause the parent's click handler to run when clicking empty margins or background layouts inside the container.
  • Assuming all events bubble: Events like focus, blur, load, unload, mouseenter, and mouseleave do not bubble. Event delegation cannot be used with these events unless you register the listener during the capturing phase by setting the capture option to true.

8. Quick Quiz

Q1: Which DOM method should you use inside an event delegation callback to ensure you get a reference to the clicked element, even if the user clicked one of its nested child elements?

A) event.target.matches()

B) event.target.closest()

Answer: B — event.target.closest() traverses up the DOM tree to locate the nearest ancestor element matching the selector.

9. Scenario-Based Challenge

The Dynamic Data Grid Action Tracker:

A data table renders rows dynamically: NameEdit. Rather than attaching separate event listeners to every button, write a single event delegation handler on the element to process edit operations.

10. Debugging Exercise

Identify the event delegation bug in this list click handler:

const list = document.getElementById('items');

list.addEventListener('click', (e) => { // Objective: Click on buttons containing class 'tag' // HTML: <button class="tag"><i>Sale</i></button> if (e.target.className === 'tag') { console.log('Tag clicked'); // fails to log when clicking on the <i> tag! Why? } });

View Solution

Diagnosis: The check e.target.className === 'tag' only matches if the user clicks the button directly. If the user clicks the nested <i> element, e.target points to the icon, and the check fails.

Fix: Use the closest() method to find the matching button element:

list.addEventListener('click', (e) => {
  const btn = e.target.closest('.tag');
  if (btn) {
    console.log('Tag clicked');
  }
});

11. Interview Questions

🟢 Q1: Describe event delegation and explain its main benefits for page performance.

Answer: Event delegation is a pattern where you attach a single event listener to a parent container instead of attaching separate listeners to each child element. When an event triggers on a child, it bubbles up to the parent container, where you inspect event.target to handle it.
The main benefits are:
Low Memory Usage: Storing a single event listener in memory instead of hundreds of listeners for individual list items.
Simplified Code: You don't need to manually attach or remove listeners when list elements are dynamically added or deleted.

12. Production Considerations

  • Non-Bubbling Events: Remember that some events (like focus, blur, mouseenter, and mouseleave) do not bubble. To use event delegation with these events, you must set the capture option to true to intercept them during the capturing phase instead.