Start · Sprachen · JavaScript · Referenz · Window: storage

Window: storage

Ereignis

Wird ausgelöst, wenn ein <em>anderes</em> Dokument desselben Ursprungs den gemeinsam genutzten <code>localStorage</code> oder <code>sessionStorage</code> ändert.

seit JavaScript Baseline: alle Browser Kategorie: webapi

Signatur

window.addEventListener("storage", handler)

Beschreibung

Das storage-Ereignis wird am Window-Objekt ausgelöst, sobald ein anderes Dokument, das denselben Speicherbereich nutzt, einen Eintrag setzt, ändert, entfernt oder den Speicher leert. Das Fenster, das die Änderung selbst vornimmt, bekommt das Ereignis nicht. Genau deshalb eignet es sich gut, um mehrere offene Tabs derselben Anwendung abzugleichen, z. B. für Abmeldung in allen Tabs, Wechsel des Designs oder einen gemeinsamen Warenkorb.

Man kann den Handler auf zwei Arten registrieren: mit window.addEventListener("storage", handler) oder über die Eigenschaft window.onstorage = handler. Der Handler erhält ein StorageEvent mit den Eigenschaften key, oldValue, newValue, url und storageArea.

Bei localStorage teilen sich alle Tabs und Fenster desselben Ursprungs den Speicher. Bei sessionStorage gilt der Speicher nur innerhalb eines Tabs (Browsing-Kontext). Das Ereignis kommt dort also praktisch nur bei gleich-originären iframes innerhalb desselben Tabs an.

Das Ereignis lässt sich nicht abbrechen und steigt nicht auf (kein Bubbling). Wird clear() aufgerufen, sind key, oldValue und newValue jeweils null.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Der Ereignisname "storage".
$handler Pflicht (event: StorageEvent) => void Callback, der ein StorageEvent erhält.
$event.key string | null Schlüssel des geänderten Eintrags, bzw. null bei clear().
$event.oldValue string | null Bisheriger Wert, bzw. null, wenn der Eintrag neu ist.
$event.newValue string | null Neuer Wert, bzw. null, wenn der Eintrag entfernt wurde.
$event.url string URL des Dokuments, das die Änderung ausgelöst hat.
$event.storageArea Storage | null Das betroffene Storage-Objekt (localStorage oder sessionStorage).

Rückgabewert

Typ
void
Beschreibung
addEventListener gibt nichts zurück.

Beispiele

Änderungen aus anderen Tabs protokollieren

window.addEventListener("storage", (event) => {
  if (event.storageArea !== localStorage) return;
  console.log(`Schlüssel: ${event.key}`);
  console.log(`Alt: ${event.oldValue} → Neu: ${event.newValue}`);
  console.log(`Quelle: ${event.url}`);
});

// In einem ANDEREN Tab desselben Ursprungs ausführen:
// localStorage.setItem("theme", "dark");
Schlüssel: theme Alt: light → Neu: dark Quelle: https://example.com/einstellungen

Abmeldung in allen Tabs gleichzeitig

const logout = () => {
  localStorage.setItem("logout", String(Date.now()));
  window.location.href = "/login";
};

window.addEventListener("storage", (event) => {
  if (event.key === "logout") {
    // Anderer Tab hat sich abgemeldet → hier ebenfalls
    window.location.href = "/login";
  }
});

document.querySelector("#logout-btn")?.addEventListener("click", logout);

Über onstorage registrieren und wieder entfernen

const syncTheme = (event) => {
  if (event.key === "theme" && event.newValue) {
    document.documentElement.dataset.theme = event.newValue;
  }
  if (event.key === null) {
    console.log("Speicher wurde geleert");
  }
};

// Variante 1: on-Property
window.onstorage = syncTheme;

// Später abmelden
window.onstorage = null;

// Variante 2: addEventListener / removeEventListener
window.addEventListener("storage", syncTheme);
window.removeEventListener("storage", syncTheme);

JSON-Daten zwischen Tabs synchronisieren

const renderCart = (items) => console.log(`Warenkorb: ${items.length} Artikel`);

window.addEventListener("storage", ({ key, newValue }) => {
  if (key !== "cart") return;
  try {
    const items = newValue ? JSON.parse(newValue) : [];
    renderCart(items);
  } catch {
    console.warn("Ungültige Warenkorb-Daten");
  }
});

// Anderer Tab:
// localStorage.setItem("cart", JSON.stringify([{ id: 1 }, { id: 2 }]));
Warenkorb: 2 Artikel

// Wichtig · Fallstricke

  • Nicht im auslösenden Tab: Das Fenster, das setItem() aufruft, bekommt kein Ereignis. Die eigene Oberfläche muss man dort direkt aktualisieren.
  • Kein Ereignis ohne echte Änderung: Wird derselbe Wert erneut gesetzt, feuern die Browser in der Regel kein Ereignis. Soll trotzdem immer ein Signal ankommen (z. B. zum Abmelden), einen Zeitstempel als Wert verwenden.
  • sessionStorage: Der Speicher gilt nur innerhalb eines Tabs. Das Ereignis erreicht daher nur gleich-originäre iframes im selben Tab, keine anderen Tabs.
  • Nur Zeichenketten: newValue und oldValue sind immer Strings oder null. JSON-Daten mit try/catch parsen.
  • Sicherheit: Werte aus dem Speicher können von jedem Skript desselben Ursprungs stammen, also auch von eingeschleustem Code. Sie nie ungeprüft in innerHTML schreiben (XSS-Gefahr).
  • Alternative: Für reine Nachrichten zwischen Tabs ist BroadcastChannel oft sauberer, weil man dafür keinen Speicher „missbrauchen“ muss.
  • Browser-Kompatibilität: Wird von allen modernen Browsern unterstützt. Im privaten Modus oder bei deaktiviertem Speicher (z. B. blockierte Drittanbieter-Cookies in iframes) kann der Zugriff auf den Speicher eine Ausnahme auslösen.