event.target and event.currentTarget
`event.target` identifies the event's target, while `event.currentTarget` identifies the object whose listener is currently running. The distinction is essential for event delegation and understanding propagation, especially when nested elements or Shadow DOM are involved.
`event.target` is the event's target: the object associated with the event at its origin. For a user click, this is often the element the user activated. In a delegated listener on a container, it can be a nested descendant rather than the container itself.
`event.currentTarget` is the object whose listener is currently being invoked. If a click bubbles from a button to its parent, the button listener sees the button as `currentTarget`, and the parent listener sees the parent. The `target` remains the button in both listeners, unless event retargeting applies.
These properties work with both capture- and bubble-phase listeners. `currentTarget` is meaningful while a listener is executing; outside that invocation, it is generally `null`. If code needs to use it asynchronously, save the value inside the listener rather than assuming it will still be set later.
Shadow DOM can retarget events as they cross a shadow boundary, so `target` observed outside a component may be the host rather than the internal node. For composed events, `composedPath()` can expose the propagation path subject to the platform's visibility rules.
Key points
- `target` identifies the event's target; `currentTarget` identifies the object whose listener is executing.
- For a bubbling child event, ancestor listeners see the child as `target` and the ancestor as `currentTarget`.
- Use `currentTarget` to refer to the element that owns a delegated listener.
- `currentTarget` is transient and generally becomes `null` after listener invocation.
- Shadow DOM may retarget `target`; `composedPath()` can help inspect the propagation path.
Interview questions
What is the difference between `event.target` and `event.currentTarget`?
`target` is the event target, commonly the element where a click originated. `currentTarget` is the node whose registered listener is running. As a bubbling event reaches ancestor listeners, `currentTarget` changes while `target` usually remains the same, except where retargeting changes the visible target.
How do `target` and `currentTarget` help implement event delegation?
A listener attached to a list container can handle clicks from its descendants because bubbling delivers those events to the container. Use `event.target` to identify the originating descendant, but verify it is the desired kind of element, for example with `closest()` and a containment check. Use `event.currentTarget` to refer to the container that owns the delegated listener. This avoids installing a separate listener on every child.
What should you consider when reading `currentTarget` in asynchronous event-handler code?
An event listener's `currentTarget` is associated with the current listener invocation, not a durable reference to the listener node. After dispatch completes, the property is generally `null`, so reading it after an `await` can produce a different result from reading it synchronously. Capture the needed node before yielding, such as `const root = event.currentTarget`. Also note that the `target` may be retargeted at a Shadow DOM boundary.
Do `target` and `currentTarget` behave differently in capture and bubble listeners?
During capture, listeners run along the path toward the target; during bubbling, eligible ancestor listeners run on the way back. In either phase, `currentTarget` identifies the node whose listener is running at that moment. `target` identifies the event's target as exposed to that listener, and Shadow DOM retargeting can affect what it exposes. `eventPhase` tells you the dispatch phase rather than the target node.