Skip to main content
← ⚑ JavaScript & the browserΒ·Module C2 Β· Lesson 8
TaskHTML has <ul id='list'><li class='item' data-id='1'>One</li><li class='item' data-id='2'>Two</li><li class='item' data-id='3'>Three</li></ul>. Add ONE listener on #list that, when an .item is clicked, logs 'clicked: <id>' using event.target.closest('.item').dataset.id.

Event delegation: one listener for a thousand items

100 XP8 min
Theory

The N-listener anti-pattern

document.querySelectorAll(".item").forEach((el) => {
  el.addEventListener("click", () => { /* ... */ });
});

Works fine for 5 items. With 5,000 items it's 5,000 listeners β†’ memory bloat + slow first paint. Worse: dynamically-added items don't get the listener and silently break.

Delegation: one listener on the parent

list.addEventListener("click", (event) => {
  const item = event.target.closest(".item");
  if (!item) return;
  // handle the click on .item β€” works for items added later too
});

Events bubble. A click on a child <li> bubbles up to its parent <ul>. One listener on the parent catches every click on any .item, present or future.

Why event.target.closest

event.target is the exact element clicked β€” might be a deeper <span> inside the item. .closest(".item") walks up until it finds the nearest matching ancestor (or returns null). That's how you distinguish "user clicked something inside an item" vs "user clicked outside any item."

React et al. do this for you

Every modern framework uses delegation at the document root for performance. You don't think about it in React. Knowing the underlying pattern is what makes the framework feel obvious instead of magic.

πŸ”’

Sign up to start coding

Theory is open to everyone. The interactive editor, live preview, and check are unlocked with a 7-day free trial β€” card required, cancel anytime.

Sign up β€” free trial β†’

First 10 lessons in each track are free. No card needed for those.

← PreviousNext lesson β†’

Get one Python or web tip a day β€” by email

Short, hand-written, no spam. Unsubscribe in one click.