addEventListener Options
`addEventListener` options configure an event listener's phase, lifetime, cancellation behavior, and cleanup. Understanding each option independently helps avoid propagation bugs and makes listener cleanup reliable.
`addEventListener(type, callback, options)` accepts either a Boolean or an options object. A Boolean selects the `capture` setting; an object can specify `capture`, `once`, `passive`, and `signal`.
`capture` determines whether the listener participates in the capture phase. If it is false, the listener is registered for the non-capture phase. The event's propagation path and whether it bubbles affect when a non-capture listener can run.
With `once: true`, the browser removes the listener after it is invoked. With `passive: true`, the listener indicates it will not call `preventDefault()`; attempting to cancel the event has no effect, and browsers may report a warning.
A valid `AbortSignal` associates the listener's lifetime with its controller. Calling `abort()` removes listeners registered with that signal. An already-aborted signal does not create an active registration. Options can be combined, but their effects are independent.
Key points
- Use an options object to specify `capture`, `once`, `passive`, or `signal`.
- `capture` controls event phase; `once` controls listener lifetime.
- `passive: true` means the listener must not cancel the event.
- Aborting the supplied signal removes its associated listener.
- Listener options describe distinct behaviors and can be combined.
Interview questions
What can the third argument to `addEventListener` be, and why use an options object?
The Boolean form sets the listener's `capture` setting. The object form can set `capture` and other options such as `once`, `passive`, and `signal`. Prefer the object form when you need to make those behaviors explicit.
How do `capture` and `once` differ?
`capture` chooses the propagation phase in which the listener is registered. `once` instead controls listener lifetime: after its first invocation, the browser removes it. A listener can use both options at once because they govern different behaviors.
What does `passive: true` guarantee, and what trade-off does it impose?
`passive: true` tells the browser the listener will not cancel the event with `preventDefault()`. This lets the browser proceed with relevant default behavior, such as scrolling, without waiting to learn whether the handler will cancel it. The handler still runs and can inspect the event, but it must not rely on cancellation.
How can `AbortSignal` help clean up event listeners in a component?
Create an `AbortController` and pass its `signal` in the listener options. When the component is disposed, call `abort()` on the controller; the browser removes listeners associated with that signal. This is especially convenient when one component owns several listeners, since they can share a signal and be cleaned up together.
What must match when removing a listener, and how does signal-based cleanup change the design?
For `removeEventListener`, the event type, callback identity, and capture setting must match the registration. Other options such as `passive` and `once` are not used to distinguish the listener for removal. If the callback was created inline and not saved, it is easy to lose the reference needed for removal; an abort signal can avoid that bookkeeping when the listener was registered with the signal.