JS
() =>
JavaScript · ES2025 · Datenstrukturen · Set
JavaScript Set Methods
union(), intersection(), difference() nativ im Browser

Jahrelang mussten Mengenoperationen in JavaScript mühsam mit filter() und has() zusammengebaut werden. Die neuen JavaScript Set Methods lösen dieses Problem mit einer sauberen, lesbaren API – direkt auf dem Set-Objekt, ohne externe Bibliotheken und ohne Workarounds.

14 Min. Lesezeit union · intersection · difference · symmetricDifference · isSubsetOf Chrome 122+ · Firefox 127+ · Safari 17+

1. Warum JavaScript so lange keine Set Methods hatte

Das Set-Objekt ist seit ES2015 in JavaScript verfügbar und löst das Problem doppelter Werte elegant. Was jedoch fehlte, waren die klassischen Mengenoperationen: Vereinigung, Schnittmenge, Differenz und symmetrische Differenz. In anderen Sprachen wie Python, Ruby oder Java gehören diese Operationen zum Standardrepertoire jeder Collection-Klasse. In JavaScript mussten Entwickler jahrelang eigene Implementierungen schreiben, die zwar funktional, aber oft fehleranfällig und schwer lesbar waren.

Der TC39-Proposal-Prozess für JavaScript Set Methods startete 2018 und durchlief alle vier Stufen bis zur Finalisierung. Die Verzögerung lag hauptsächlich in API-Design-Fragen: Sollen die Methoden mutierend oder nicht-mutierend sein? Sollen sie nur andere Set-Instanzen akzeptieren oder beliebige Iterables? Die finale Entscheidung war, die Set Methods nicht-mutierend zu gestalten – jede Methode gibt ein neues Set zurück statt das ursprüngliche zu verändern. Damit folgen sie dem Immutability-Prinzip moderner JavaScript-APIs. Und sie akzeptieren beliebige Set-ähnliche Objekte, nicht nur exakte Set-Instanzen.

2. union(): Vereinigungsmenge zweier Sets

Die Methode union() gibt ein neues Set zurück, das alle Elemente aus beiden Sets enthält – ohne Duplikate, da Sets per Definition keine doppelten Elemente haben. Das Ergebnis-Set enthält genau jene Werte, die in Set A oder in Set B vorkommen. Die Methode ist symmetrisch: a.union(b) und b.union(a) liefern Sets mit identischem Inhalt, auch wenn die interne Reihenfolge abweichen kann.

In der Praxis begegnet uns union() überall dort, wo zwei unabhängige Quellen zusammengeführt werden sollen, ohne dass Duplikate entstehen. Ein typisches Szenario: ein Nutzer hat Berechtigungen aus seiner Rolle und aus explizit zugewiesenen Rechten. Das Set der effektiven Berechtigungen ist die Vereinigung beider Sets. Ohne Set Methods wäre das ein spread-Operator in ein neues Set: new Set([...rolePermissions, ...explicitPermissions]). Mit union() ist die Intention klarer und das Ergebnis dasselbe.


// Set Methods — union, intersection, difference examples
const frontend = new Set(['React', 'Vue', 'Angular', 'Svelte']);
const backend = new Set(['Node.js', 'Python', 'Go', 'React']); // React appears in both

// union(): all technologies from both sets, no duplicates
const allTech = frontend.union(backend);
// Set { 'React', 'Vue', 'Angular', 'Svelte', 'Node.js', 'Python', 'Go' }

// intersection(): only technologies present in both sets
const fullstack = frontend.intersection(backend);
// Set { 'React' }

// difference(): technologies in frontend but NOT in backend
const frontendOnly = frontend.difference(backend);
// Set { 'Vue', 'Angular', 'Svelte' }

// symmetricDifference(): technologies in exactly one of the two sets
const unique = frontend.symmetricDifference(backend);
// Set { 'Vue', 'Angular', 'Svelte', 'Node.js', 'Python', 'Go' }

// Chain multiple Set Methods
const result = frontend
  .union(new Set(['TypeScript', 'Rust']))
  .difference(new Set(['Angular']));
// Set { 'React', 'Vue', 'Svelte', 'TypeScript', 'Rust' }

3. intersection(): Schnittmenge berechnen

Die Methode intersection() gibt ein neues Set zurück, das nur jene Elemente enthält, die in beiden Sets vorkommen. Mathematisch ist das die Schnittmenge A ∩ B. Sie ist die nützlichste der neuen Set Methods für Filteraufgaben: Gegeben eine Menge von IDs aus einer Datenbank und eine Menge von erlaubten IDs – welche IDs darf der Nutzer sehen? Die Antwort ist die Schnittmenge, berechnet mit einem einzigen intersection()-Aufruf.

Der interne Algorithmus der Set Methods-Implementierung ist klug: Wenn eines der Sets deutlich kleiner ist, iteriert der Algorithmus über das kleinere Set und prüft für jedes Element, ob es im größeren Set vorkommt. Das ist effizienter als beide Sets vollständig zu durchlaufen. Wer zwei sehr unterschiedlich große Sets schneidet, profitiert von dieser Optimierung automatisch. In der Praxis macht das bei großen Datensätzen einen messbaren Unterschied gegenüber dem manuellen Array-Workaround.

4. difference(): Differenzmenge und was sie bedeutet

Die Methode difference() gibt ein neues Set zurück, das die Elemente aus dem ersten Set enthält, die nicht im zweiten Set vorkommen. Mathematisch ist das A \ B oder A − B. Die Methode ist nicht kommutativ: a.difference(b) und b.difference(a) geben in der Regel unterschiedliche Ergebnisse. Das macht intuitiven Sinn: "Elemente in A, die nicht in B sind" ist eine andere Frage als "Elemente in B, die nicht in A sind".

Ein konkreter Anwendungsfall: Ein E-Commerce-System hat eine Menge aller Produkt-IDs im Katalog und eine Menge der IDs, die bereits im Warenkorb liegen. Die Differenz ergibt die Produkte, die noch nicht im Warenkorb sind – nützlich für Empfehlungsalgorithmen oder für das Anzeigen noch nicht gekaufter Artikel. Mit den neuen JavaScript Set Methods ist diese Berechnung eine einzige lesbare Zeile. Frühere Implementierungen nutzten filter(id => !cart.has(id)) auf Arrays, was eine Umwandlung zwischen Set und Array erforderte.

5. symmetricDifference(): Elemente in genau einem Set

Die symmetricDifference()-Methode gibt ein Set aller Elemente zurück, die in genau einem der beiden Sets vorkommen – also die Elemente, die nicht in der Schnittmenge liegen. Mathematisch ist das A △ B = (A ∪ B) \ (A ∩ B). Diese Set Method ist die mathematisch eleganteste der Gruppe und wird in Szenarien genutzt, wo man herausfinden möchte, was sich zwischen zwei Zuständen geändert hat.

Der typische Anwendungsfall für symmetricDifference() sind Diff-Algorithmen für Sets: Gegeben die Menge der aktiven Feature-Flags vor einer Deployment-Session und danach – welche Flags wurden aktiviert oder deaktiviert? Die symmetrische Differenz liefert genau diese Menge der geänderten Flags, ohne zu unterscheiden, ob sie hinzugefügt oder entfernt wurden. Wenn man diese Information braucht, kombiniert man sie mit difference() in beide Richtungen: hinzugefügte Flags sind after.difference(before), entfernte Flags sind before.difference(after).


// Practical permission system using Set Methods
const rolePermissions = new Set(['read', 'write', 'comment']);
const adminPermissions = new Set(['read', 'write', 'delete', 'manage-users', 'export']);
const explicitGrants = new Set(['export', 'audit-log']);
const explicitRevokes = new Set(['comment']);

// Effective permissions: (role union explicit grants) minus revokes
const effectivePermissions = rolePermissions
  .union(explicitGrants)
  .difference(explicitRevokes);
// Set { 'read', 'write', 'export', 'audit-log' }

// What permissions does this user lack compared to admin?
const missingPermissions = adminPermissions.difference(effectivePermissions);
// Set { 'delete', 'manage-users' }

// Are all effective permissions a subset of admin?
const isSafeSubset = effectivePermissions.isSubsetOf(adminPermissions);
// false — 'audit-log' is not in adminPermissions

// Feature flag diff — what changed between deployments?
const flagsBefore = new Set(['dark-mode', 'new-checkout', 'beta-search']);
const flagsAfter = new Set(['dark-mode', 'new-checkout', 'stable-search', 'ai-recommend']);

const added = flagsAfter.difference(flagsBefore);    // Set { 'stable-search', 'ai-recommend' }
const removed = flagsBefore.difference(flagsAfter);  // Set { 'beta-search' }
const changed = flagsBefore.symmetricDifference(flagsAfter); // Set { 'beta-search', 'stable-search', 'ai-recommend' }

6. isSubsetOf(), isSupersetOf(), isDisjointFrom()

Neben den Methoden, die neue Sets zurückgeben, bieten die JavaScript Set Methods drei boolesche Prüfmethoden. isSubsetOf(other) prüft, ob alle Elemente des Aufrufer-Sets auch im anderen Set vorhanden sind – mathematisch A ⊆ B. isSupersetOf(other) ist die Umkehrung und prüft, ob das Aufrufer-Set alle Elemente des anderen enthält. isDisjointFrom(other) prüft, ob die beiden Sets keine gemeinsamen Elemente haben, also ob ihre Schnittmenge leer ist.

Diese Prüfmethoden sind besonders nützlich für Validierungen und Guards. Beispiel: Ein Upload-Handler akzeptiert nur bestimmte MIME-Typen. Statt jeden empfangenen Typ einzeln zu prüfen, kann man prüfen, ob die Menge der empfangenen MIME-Typen eine Teilmenge der erlaubten Typen ist. receivedTypes.isSubsetOf(allowedTypes) gibt true zurück, wenn alle empfangenen Typen erlaubt sind. Das ist semantisch präziser und lesbarer als eine every()-Prüfung über ein Array. Alle drei booleschen Set Methods akzeptieren, wie alle anderen Set Methods, auch beliebige Set-ähnliche Objekte.

7. Praxisbeispiele: Filter, Berechtigungen, Diff-Algorithmen

Die JavaScript Set Methods leuchten besonders in drei Domänen: Berechtigungssystemen, Filterlogik und Änderungsverarbeitung. In einem rollenbasierten Zugriffssystem berechnet man die effektiven Rechte eines Nutzers aus der Union seiner Rollen-Permissions minus der expliziten Revokes. Dann prüft man mit requiredPermissions.isSubsetOf(effectivePermissions), ob der Nutzer eine Operation ausführen darf. Dieser Ansatz ist deklarativer und präziser als eine Kaskade von includes()-Prüfungen.

Für Filteranwendungen in UI-Komponenten sind Sets ideal, wenn Tags, Kategorien oder Attribute als Filterkriterien genutzt werden. Ein Artikel mit den Tags {'React', 'TypeScript', 'Performance'} und ein aktiver Filter {'React', 'TypeScript'}: Der Artikel erscheint, wenn activeFilter.isSubsetOf(articleTags) wahr ist – alle Filterbedingungen müssen erfüllt sein. Für OR-Logik (mindestens ein Filter trifft zu) prüft man, ob die Schnittmenge nicht leer ist: activeFilter.intersection(articleTags).size > 0. Diese Ausdrücke sind für Entwickler unmittelbar lesbar, weil die Set Methods die mathematische Logik direkt widerspiegeln.

8. Performance: Set Methods vs. Array-Workarounds

Der Performance-Vorteil der JavaScript Set Methods kommt aus zwei Quellen. Erstens haben Set-Lookups O(1)-Komplexität gegenüber O(n) für Array-Includes. Ein Array-Workaround wie a.filter(x => b.includes(x)) hat O(n²)-Komplexität, weil für jedes Element von A die gesamte Länge von B durchsucht wird. Der entsprechende Set Method-Aufruf a.intersection(b) hat O(min(|A|, |B|))-Komplexität. Bei Sets mit tausenden Elementen ist dieser Unterschied erheblich.

Die zweite Performance-Quelle ist die Vermeidung von Array-Konvertierungen. Viele Workarounds folgen dem Muster: Set → Array (via spread) → filter/map → neues Set. Jede Konvertierung kostet Zeit und Speicher. Die Set Methods arbeiten direkt auf Set-Internals ohne Zwischenkonvertierungen. Für kleine Sets ist der Unterschied vernachlässigbar. Für Sets mit Tausenden bis Millionen von Elementen – typisch in Datenverarbeitungs-Pipelines, Caches oder ID-Verwaltung – ist die asymptotisch bessere Komplexität ein echter Vorteil, der sich in Millisekunden niederschlägt.


// Performance comparison — Set Methods vs. Array workarounds
// Both produce identical results, but Set Methods are O(min(n,m)) vs O(n*m)

const setA = new Set(Array.from({ length: 10000 }, (_, i) => i));
const setB = new Set(Array.from({ length: 8000 }, (_, i) => i * 1.2 | 0));

// Old workaround: O(n * m) — array includes is O(m) for each element
const arrA = [...setA];
const arrB = [...setB];
const intersectionOld = new Set(arrA.filter((x) => arrB.includes(x)));

// New Set Method: O(min(n, m)) — native hash lookup
const intersectionNew = setA.intersection(setB);

// Both results are equivalent, but the Set Method is dramatically faster at scale

// Chaining Set Methods — readable multi-step pipeline
const allowedCountries = new Set(['DE', 'AT', 'CH', 'LU', 'LI']);
const activeCountries = new Set(['DE', 'AT', 'US', 'GB', 'FR']);
const blockedCountries = new Set(['FR', 'GB']);

const targetCountries = allowedCountries
  .intersection(activeCountries)     // DE, AT
  .union(new Set(['CH']))            // DE, AT, CH
  .difference(blockedCountries);     // DE, AT, CH (no change here)

9. Set Methods im direkten Vergleich zu Workarounds

Bevor die JavaScript Set Methods verfügbar waren, mussten Entwickler Mengenoperationen manuell implementieren. Die folgenden Gegenüberstellungen zeigen, wie viel kürzer, lesbarer und effizienter der neue Code ist. Die Verbesserung bei Lesbarkeit und Intention ist dabei mindestens genauso wertvoll wie die Performance-Gewinne.

Operation Alter Workaround Neue Set Method Komplexität
Vereinigung new Set([...a, ...b]) a.union(b) O(n+m) → O(n+m)
Schnittmenge new Set([...a].filter(x => b.has(x))) a.intersection(b) O(n) → O(min(n,m))
Differenz new Set([...a].filter(x => !b.has(x))) a.difference(b) O(n) → O(n)
Teilmenge? [...a].every(x => b.has(x)) a.isSubsetOf(b) O(n) → O(n)
Disjunkt? [...a].every(x => !b.has(x)) a.isDisjointFrom(b) O(n) → O(min(n,m))

Bemerkenswert ist, dass alle JavaScript Set Methods nicht nur exakte Set-Instanzen akzeptieren, sondern beliebige Set-ähnliche Objekte. Das Protokoll erfordert eine size-Eigenschaft und eine has()-Methode sowie einen keys()-Iterator. Das bedeutet, dass eigene Collection-Klassen und sogar Map-Objekte als Argumente übergeben werden können – solange sie das Protokoll implementieren. Diese Design-Entscheidung macht die Set Methods deutlich flexibler als eine reine Set-zu-Set-API.

Mironsoft

Modernes JavaScript, Performance-Optimierung und skalierbare Frontend-Architekturen

JavaScript-Code auf modernen Stand bringen?

Wir modernisieren bestehende JavaScript-Codebasen, ersetzen veraltete Workarounds durch neue APIs wie Set Methods und verbessern Performance und Lesbarkeit nachhaltig.

Code-Modernisierung

Veraltete Array-Workarounds durch Set Methods, Map-APIs und moderne Iterator-Protokolle ersetzen

Performance-Review

O(n²)-Hotspots in Datenverarbeitungs-Pipelines identifizieren und mit nativen Datenstrukturen lösen

Schulung

Team-Workshops zu modernem JavaScript – ES2023 bis ES2025 Features mit konkreten Anwendungsfällen

10. Zusammenfassung

Die JavaScript Set Methodsunion(), intersection(), difference(), symmetricDifference(), isSubsetOf(), isSupersetOf() und isDisjointFrom() – schließen eine lange bestehende Lücke in der JavaScript-Standardbibliothek. Mengenoperationen, die bisher mit fehleranfälligen Array-Workarounds oder externen Bibliotheken umgesetzt wurden, sind nun direkt auf dem Set-Objekt verfügbar. Die nicht-mutierende API gibt immer neue Sets zurück und ermöglicht Methodenketten, die komplexe Logik in lesbaren, deklarativen Ausdrücken ausdrücken.

Die Browser-Unterstützung ist seit 2024 vollständig in allen modernen Browsern. Wer ältere Browser unterstützen muss, kann das core-js-Polyfill oder eine eigene Shim-Implementierung nutzen, die dieselbe API-Oberfläche bietet. Für neue Projekte und Code-Modernisierungen sind die Set Methods die erste Wahl für jede Logik, die mit Mengen von eindeutigen Werten arbeitet – von Berechtigungssystemen über Tag-Filter bis zu Feature-Flag-Diffs.

JavaScript Set Methods — Das Wichtigste auf einen Blick

Neue Mengen-Methoden

union(), intersection(), difference(), symmetricDifference() – alle geben ein neues Set zurück, sind nicht-mutierend und unterstützen Methodenketten.

Boolesche Prüfmethoden

isSubsetOf(), isSupersetOf(), isDisjointFrom() – für Validierungen und Guards ohne Array-Konvertierung.

Performance

intersection() ist O(min(n,m)) statt O(n²) beim Array-Workaround. Keine Zwischenkonvertierungen zwischen Set und Array nötig.

Browser-Support

Chrome 122+, Firefox 127+, Safari 17+. Polyfill via core-js für ältere Browser. Akzeptieren beliebige Set-ähnliche Objekte mit has() und size.

11. FAQ: JavaScript Set Methods

1Sind Set Methods mutierend?
Nein. Alle Set Methods geben ein neues Set zurück und lassen die Originale unverändert. Das macht Methodenketten sicher und entspricht modernen Immutability-Prinzipien.
2Welche Browser unterstützen Set Methods?
Chrome 122+, Firefox 127+, Safari 17+, Edge 122+. Vollständige Unterstützung seit 2024. Polyfill via core-js für ältere Browser.
3Nur Set-Instanzen als Argumente?
Nein. Beliebige Set-ähnliche Objekte mit size, has() und keys() werden akzeptiert. Auch eigene Collection-Klassen und Map-Objekte funktionieren als Argument.
4difference() vs. symmetricDifference()?
difference() gibt A minus B — Elemente in A, nicht in B. symmetricDifference() gibt (A minus B) plus (B minus A) — alle Elemente, die in genau einem der Sets vorkommen.
5Warum ist intersection() effizienter?
Die native Implementierung iteriert über das kleinere der beiden Sets — O(min(n,m)). Der Array-Workaround iteriert immer über das erste Array, auch wenn es viel größer ist.
6Map als Argument übergeben?
Ja. Map implementiert das Set-ähnliche Protokoll mit size und has(). Map.keys() liefert den benötigten Iterator. Der Aufrufer muss ein Set sein, das Argument kann Map oder Custom-Collection sein.
7Polyfill für ältere Browser?
import 'core-js/proposals/set-methods-v2' oder das npm-Paket set-methods-polyfill. TypeScript: lib in tsconfig.json auf 'ES2025' oder 'ESNext' setzen.
8Set Methods verketten?
Ja. a.union(b).intersection(c).difference(d) ist valid. Jeder Schritt erstellt ein neues Set — bei sehr großen Sets und vielen Schritten kann das speicherrelevant sein.
9Was gibt isDisjointFrom() zurück?
true wenn keine gemeinsamen Elemente vorhanden — Schnittmenge leer wäre. false wenn mindestens ein gemeinsames Element existiert. Nützlich für Konfliktprüfungen.
10Welchen TC39-Stage haben die Set Methods?
Stage 4 — Teil des ECMAScript 2025 Standards. Kein Proposal mehr, sondern normierter Bestandteil der JavaScript-Sprachspezifikation.