Event Delegation in JavaScript: How It Works + Performance Patterns
A deep, interview-ready guide to event delegation: bubbling/capturing, delegation patterns, performance benefits, common pitfalls, and clean implementations for real UIs.
Frontend Interview Team
February 08, 2026
Event delegation is a high-signal topic because it tests your understanding of:
30‑second interview answer
Event delegation means attaching one event listener on a parent and handling events for children using bubbling. It’s faster (fewer listeners), uses less memory, and works for dynamically added elements. The common pattern is e.target.closest(selector) to find the intended target.
Key points
- Delegation relies on bubbling.
- One listener beats thousands.
- Use
closestto match actionable elements. - Be careful with stopPropagation and nested handlers.
- DOM events
- propagation
- performance
- dynamic UIs
1) The problem delegation solves
If you attach listeners to many items:
document.querySelectorAll('.item').forEach((el) => {
el.addEventListener('click', () => {
// ...
});
});Problems:
- many listeners (memory)
- expensive setup
- doesn’t handle dynamically added items unless you re-bind
2) Event propagation: capturing vs bubbling
Events travel in phases:
- capturing (top → down)
- target
- bubbling (target → up)
Most events bubble.
parent.addEventListener('click', handler); // default uses bubbling
parent.addEventListener('click', handler, true); // capturing3) Delegation pattern (core idea)
Attach one listener to a common ancestor and decide what was clicked.
const list = document.querySelector('#list');
list.addEventListener('click', (e) => {
const item = e.target.closest('.item');
if (!item) return;
console.log('Clicked item id:', item.dataset.id);
});Key tool: closest().
4) Why delegation improves performance
- fewer listeners
- less memory
- faster startup
- supports dynamic children naturally
Delegation is especially useful for:
- tables
- lists
- menus
- infinite scroll feeds
5) Common pitfalls
A) e.target vs e.currentTarget
target= the deepest element clickedcurrentTarget= element with the listener
B) stopPropagation()
If a child calls stopPropagation, delegated listener won’t run.
C) Non-bubbling events
Some events don’t bubble (e.g., focus), but you can use focusin.
6) Delegation with multiple actions
container.addEventListener('click', (e) => {
const btn = e.target.closest('button[data-action]');
if (!btn) return;
const action = btn.dataset.action;
const row = btn.closest('[data-id]');
const id = row?.dataset.id;
if (action === 'delete') deleteRow(id);
if (action === 'edit') editRow(id);
});7) Interview Q&A
Q: Why use event delegation?
- performance + works with dynamic elements.
Q: How do you find the element you care about?
e.target.closest(selector).
Q: What’s bubbling vs capturing?
- bubbling goes from target up; capturing goes from root down.
Summary checklist
- I can explain bubbling/capturing.
- I can implement delegation with
closest. - I can explain why it helps performance.
- I know stopPropagation can break delegation.
Summary
- Delegation = one listener on parent + detect targets.
- It reduces listeners and handles dynamic UI.
- Use
closestand understand propagation.