Skip to content

Event listeners

Every addEventListener registers the handler on the target (or capture root). The target holds the listener list — a retention path.

flowchart TD
  bus[EventTarget]
  h1[handler 1 + closure]
  h2[handler 2 + closure]
  data1[large payload A]
  data2[large payload B]
  bus --> h1
  bus --> h2
  h1 --> data1
  h2 --> data2
function subscribe(userId) {
const profile = loadHugeProfile(userId);
window.addEventListener('scroll', () => {
track(profile.id); // profile retained by handler
});
// re-called on every route visit → duplicate listeners
}
const controller = new AbortController();
function subscribe(userId) {
const profile = loadProfile(userId);
window.addEventListener(
'scroll',
() => track(profile.id),
{ signal: controller.signal }
);
}
function unsubscribe() {
controller.abort(); // removes all listeners using this signal
}

Live demo: duplicate event listeners

Each "subscribe" adds another listener that closes over large data.

— MBPeak: — MB