Start · Sprachen · JavaScript · Referenz · EventTarget

EventTarget

Schnittstelle

Basis-Interface für alle Objekte, die Ereignisse empfangen, Listener registrieren und Events per <code>dispatchEvent()</code> auslösen können.

seit JavaScript Baseline: alle Browser; Konstruktor new EventTarge Kategorie: webapi

Signatur

interface EventTarget

Beschreibung

EventTarget ist das grundlegende Interface des DOM-Ereignismodells. Alle Objekte, die Ereignisse empfangen können, implementieren es, zum Beispiel Element, Document, Window, XMLHttpRequest, WebSocket, AbortSignal, Worker oder MediaQueryList. Es stellt genau drei Methoden bereit: addEventListener(), removeEventListener() und dispatchEvent().

Seit einigen Jahren lässt sich EventTarget auch direkt über new EventTarget() erzeugen oder per class MyEmitter extends EventTarget erweitern. Damit bekommt man einen leichtgewichtigen, standardkonformen Event-Emitter, ohne eine Bibliothek einzubinden oder DOM-Knoten zu missbrauchen. Das eignet sich für Stores, Service-Klassen oder die Kommunikation zwischen Modulen.

Listener lassen sich über ein Optionsobjekt feiner steuern: once entfernt den Listener nach dem ersten Aufruf automatisch, passive sichert dem Browser zu, dass preventDefault() nicht aufgerufen wird (das verbessert die Scroll-Leistung), capture registriert den Listener für die Capture-Phase, und mit signal kann man Listener über einen AbortController gesammelt entfernen.

Eigene Ereignisse erzeugt man mit new Event() oder new CustomEvent(), wobei CustomEvent Nutzdaten in detail mitgibt. dispatchEvent() ruft die Listener synchron auf und gibt false zurück, wenn ein abbrechbares Event per preventDefault() abgebrochen wurde.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Ereignistyp für addEventListener/removeEventListener, z. B. "click". Groß- und Kleinschreibung wird unterschieden.
$listener Pflicht Function | { handleEvent(event) } | null Callback-Funktion oder Objekt mit einer Methode handleEvent(), das beim Ereignis aufgerufen wird.
$options boolean | { capture?: boolean, once?: boolean, passive?: boolean, signal?: AbortSignal } false Ein boolescher Wert entspricht capture. Das Objekt steuert Capture-Phase, einmalige Ausführung, passives Verhalten und das Entfernen per AbortSignal.
$event Pflicht Event Das Event-Objekt, das an dispatchEvent() übergeben und an alle passenden Listener ausgeliefert wird.

Rückgabewert

Typ
EventTarget
Beschreibung
new EventTarget() liefert eine neue Instanz. addEventListener() und removeEventListener() geben undefined zurück. dispatchEvent() gibt einen boolean zurück: false, wenn das Event abbrechbar war und preventDefault() aufgerufen wurde, sonst true.

Beispiele

Eigenständiges EventTarget erzeugen und nutzen

const bus = new EventTarget();

bus.addEventListener('user:login', (e) => {
  console.log(`Willkommen, ${e.detail.name}!`);
});

bus.dispatchEvent(new CustomEvent('user:login', { detail: { name: 'Anna' } }));
Willkommen, Anna!

Eigene Klasse als Event-Emitter (Warenkorb)

class Warenkorb extends EventTarget {
  #artikel = [];

  hinzufuegen(artikel) {
    this.#artikel.push(artikel);
    this.dispatchEvent(new CustomEvent('change', {
      detail: { anzahl: this.#artikel.length }
    }));
  }
}

const korb = new Warenkorb();
korb.addEventListener('change', (e) => {
  console.log('Artikel im Korb:', e.detail.anzahl);
});

korb.hinzufuegen({ id: 1, name: 'Buch' });
korb.hinzufuegen({ id: 2, name: 'Stift' });
Artikel im Korb: 1 Artikel im Korb: 2

Mehrere Listener per AbortController entfernen

const controller = new AbortController();
const { signal } = controller;

window.addEventListener('resize', () => console.log('resize'), { signal });
window.addEventListener('scroll', () => console.log('scroll'), { signal, passive: true });
document.addEventListener('keydown', (e) => console.log(e.key), { signal });

// Später, z. B. beim Abbau einer Komponente:
controller.abort(); // entfernt alle drei Listener auf einmal

Abbrechbares Event und Rückgabewert von dispatchEvent

const formular = new EventTarget();

formular.addEventListener('beforesave', (e) => {
  if (!e.detail.email.includes('@')) {
    e.preventDefault(); // Speichern verhindern
  }
});

const speichern = (daten) => {
  const ok = formular.dispatchEvent(
    new CustomEvent('beforesave', { detail: daten, cancelable: true })
  );
  console.log(ok ? 'Gespeichert' : 'Abgebrochen');
};

speichern({ email: 'test@example.com' });
speichern({ email: 'ungueltig' });
Gespeichert Abgebrochen

// Wichtig · Fallstricke

  • Gleiche Funktionsreferenz: removeEventListener() entfernt nur, wenn type, dieselbe Funktionsreferenz und derselbe capture-Wert übergeben werden. Anonyme Pfeilfunktionen lassen sich so nicht entfernen. In dem Fall hilft { signal } oder { once: true }.
  • Doppelte Registrierung: Wird derselbe Listener mit identischem type und capture mehrfach registriert, wird er nur einmal aufgerufen.
  • Synchron: dispatchEvent() ruft alle Listener sofort und synchron auf, noch bevor die Methode zurückkehrt. Eine Ausnahme in einem Listener bricht die übrigen Listener nicht ab, sie wird aber gemeldet (reportError).
  • Kein Bubbling ohne Baum: Ein alleinstehendes EventTarget hat keine Eltern. bubbles und capture haben dort keine Wirkung.
  • Event wiederverwenden: Ein Event-Objekt kann während der laufenden Auslieferung nicht erneut ausgelöst werden (InvalidStateError).
  • this in Listenern: Bei normalen Funktionen verweist this auf currentTarget, bei Pfeilfunktionen nicht.
  • Passive Listener: Chrome und Firefox setzen passive für touchstart, touchmove und wheel auf window, document und body standardmäßig auf true. Ein Aufruf von preventDefault() wird dort ignoriert.
  • Kompatibilität: Die Methoden werden überall unterstützt. Den Konstruktor bzw. extends EventTarget gibt es erst seit Chrome 64, Firefox 59, Safari 14 und Node.js 15. Die Option signal gibt es ab Chrome 90, Firefox 86, Safari 15. Im alten Internet Explorer (unter 9) gab es stattdessen attachEvent.