Event Delegation
Event delegation lets a parent element respond to events originating from matching descendants by using event bubbling. It reduces the number of individual event listeners and works especially well for dynamic lists and other changing DOM structures.
When an event occurs on an element, it can bubble upward through its ancestors. A listener placed on a parent can therefore inspect `event.target` and determine whether the original event came from an element it should handle.
A common pattern is to attach one listener to a stable container and use `target.closest()` to find the relevant descendant. Before acting, verify that the matched element belongs to the intended container so that nested elements or unrelated descendants are not handled accidentally.
Delegation is particularly useful when children are added or removed dynamically. Newly inserted matching elements can be handled without registering another listener for each element, because the listener already exists on the parent.
Not every event behaves the same way. Delegation relies on propagation to the ancestor, so event types that do not bubble normally require a different approach or an event-specific strategy. `stopPropagation()` can also prevent an event from reaching the delegated listener.
Key points
- Use a parent listener and inspect the originating descendant.
- Event bubbling carries the event toward ancestors.
- `event.target` is the original event target; `event.currentTarget` is the element whose listener is running.
- Delegation naturally handles matching elements added later.
- Check the matched element's relationship to the container before acting.
Interview questions
How would you implement delegated clicks for a dynamic list?
Attach one `click` listener to the list container. Inside the handler, use `event.target.closest()` to find the relevant button or item. Then verify that the match belongs to the container before performing the action. This also handles matching elements added later without attaching new listeners.
What is the difference between `event.target` and `event.currentTarget` in delegated events?
`event.target` is the element where the event originally occurred, while `event.currentTarget` is the element whose listener is currently handling the event. With delegation, `currentTarget` is typically the parent container and `target` may be a deeply nested child. This distinction lets the handler determine which descendant triggered the delegated action.
What are the limitations of event delegation?
Delegation depends on the event reaching the ancestor, so events that do not bubble normally cannot simply be handled this way. Propagation can also be interrupted by code such as `stopPropagation()`. Complex selectors or very broad containers can make handlers harder to reason about, so the delegated handler should narrowly identify the intended descendants.
What is event delegation, and why would you use it?
Event delegation means placing an event listener on an ancestor instead of attaching separate listeners to each child. The ancestor can inspect the event target after the event bubbles upward and decide which descendant should be handled. This can reduce listener count and makes dynamic child elements easier to support.