Back

Was ist der Unterschied zwischen Map, Set und Object in JavaScript?

Was ist der Unterschied zwischen Map, Set und Object in JavaScript?

Sie refaktorieren eine Komponente und müssen Schlüssel-Wert-Paare speichern. Aus Gewohnheit greifen Sie zu einem Object, dann halten Sie inne. Sollte das eine Map sein? Würde ein Set hier besser funktionieren? Diese Entscheidung ist wichtiger, als es scheint – jede Struktur hat unterschiedliche Performance-Eigenschaften und semantische Bedeutungen, die die Klarheit und Effizienz Ihres Codes beeinflussen.

Dieser Vergleich von JavaScript-Datenstrukturen schlüsselt die praktischen Unterschiede zwischen Map, Set und Object auf, damit Sie die richtige Wahl für Produktionscode treffen können.

Wichtigste Erkenntnisse

  • Objects konvertieren Schlüssel zu Strings, während Maps Schlüsseltypen exakt beibehalten – diese Unterscheidung verhindert subtile Kollisionsfehler.
  • Maps übertreffen Objects bei häufigen Hinzufügungen und Löschungen, während Objects bei lesezentrierten Workloads mit stabilen Strukturen besser abschneiden.
  • Sets bieten O(1)-Mitgliedschaftsprüfungen und enthalten jetzt native union-, intersection- und difference-Methoden in modernem JavaScript.
  • Verwenden Sie standardmäßig Objects für strukturierte Daten, greifen Sie zu Maps, wenn Schlüssel dynamisch oder nicht-String sind, und nutzen Sie Sets, wenn Eindeutigkeit Ihr Hauptanliegen ist.

Kernzweck: Wann Map vs. Set vs. Object verwenden

Der Unterschied zwischen Map und Object in JavaScript läuft auf Intention und Schlüsselbehandlung hinaus:

  • Object: Strukturierte Daten mit bekannten String/Symbol-Schlüsseln. Denken Sie an Konfiguration, Komponenten-Props, API-Antworten.
  • Map: Dynamische Schlüssel-Wert-Sammlungen, bei denen Schlüssel jeden Typ haben können. Denken Sie an Caches, Lookup-Tabellen mit Object-Schlüsseln, häufige Hinzufügungen und Löschungen.
  • Set: Sammlungen eindeutiger Werte ohne Schlüssel. Denken Sie an Deduplizierung, Tracking gesehener Elemente, Mitgliedschaftsprüfungen.

Schlüsselbehandlung: Der fundamentale Unterschied zwischen Map und Object

Objects konvertieren Schlüssel zu Strings. Maps bewahren Schlüsseltypen exakt.

const obj = {}
obj[1] = 'number'
obj['1'] = 'string'
console.log(Object.keys(obj)) // ['1'] — Kollision

const map = new Map()
map.set(1, 'number')
map.set('1', 'string')
console.log(map.size) // 2 — unterschiedliche Schlüssel

Maps akzeptieren auch Objects als Schlüssel – etwas, das Objects grundsätzlich nicht ohne Serialisierungs-Workarounds können.

const userCache = new Map()
const user = { id: 42 }
userCache.set(user, { lastSeen: Date.now() })

Siehe die MDN-Dokumentation für Map für vollständige Schlüsselsemantik.

Iterations- und Reihenfolgesemantik

Alle drei Strukturen haben eine definierte Iterationsreihenfolge, aber die Semantik unterscheidet sich:

Map und Set: Reine Einfügereihenfolge. Immer.

Object: Einfügereihenfolge für String-Schlüssel, aber integer-indizierte Schlüssel (z.B. '1', '42') werden numerisch zuerst sortiert. Das überrascht Entwickler:

const obj = { b: 1, 2: 2, a: 3, 1: 4 }
console.log(Object.keys(obj)) // ['1', '2', 'b', 'a']

Maps und Sets sind direkt mit for...of iterierbar. Objects erfordern Object.keys(), Object.values() oder Object.entries().

Performance-Eigenschaften im großen Maßstab

Für die Frage nach JavaScript Map vs. Set vs. Object Performance kommt es auf den Kontext an:

Objects glänzen bei lesezentrierten Workloads mit String-Schlüsseln. Moderne Engines wie V8 optimieren Eigenschaftszugriffe durch Hidden Classes, was Lesevorgänge sehr schnell macht – wenn die Object-Form stabil bleibt.

Maps gewinnen bei häufigen Hinzufügungen und Löschungen. Das Löschen von Object-Eigenschaften (via delete) kann Deoptimierung auslösen, indem es Hidden Classes invalidiert. Die ECMAScript-Spezifikation garantiert sublineare durchschnittliche Zugriffszeit für Maps, ohne eine spezifische interne Implementierung vorzuschreiben.

Sets bieten O(1)-Mitgliedschaftsprüfungen via has() und übertreffen Array-includes() bei jeder nicht-trivialen Collection-Größe.

Native Set-Operationen

Set enthält jetzt eingebaute Methoden für gängige Operationen (siehe MDN-Dokumentation für Set):

const a = new Set([1, 2, 3])
const b = new Set([2, 3, 4])

a.union(b)               // Set {1, 2, 3, 4}
a.intersection(b)        // Set {2, 3}
a.difference(b)          // Set {1}
a.symmetricDifference(b) // Set {1, 4}
a.isSubsetOf(b)          // false

Diese Methoden werden in modernen Browsern weitgehend unterstützt.

Praktische Frontend-Szenarien

Object verwenden, wenn:

  • Sie Komponenten-Props oder Konfiguration definieren
  • Sie mit JSON-Serialisierung arbeiten (Maps serialisieren nicht direkt)
  • Schlüssel zur Schreibzeit bekannt sind

Map verwenden, wenn:

  • Schlüssel dynamisch oder benutzerbereitgestellt sind (vermeidet Prototype Pollution)
  • Sie Object-Referenzen als Schlüssel benötigen
  • Größen-Tracking wichtig ist (map.size vs. Object.keys(obj).length)
  • Sie Caches mit häufigen Updates erstellen

Set verwenden, wenn:

  • Sie eindeutige IDs oder gesehene Elemente tracken
  • Sie Arrays deduplizieren: [...new Set(array)]
  • Schnelle Mitgliedschaftstests benötigt werden

Kurzreferenz

MerkmalObjectMapSet
Schlüsseltypenstring, symbolbeliebigN/A (nur Werte)
GrößeObject.keys().length.size.size
Iterationindirektdirektdirekt
JSON-Unterstützungnativmanuellmanuell
Prototype-Risikojaneinnein

Fazit

Die Wahl zwischen Map, Set und Object ist nicht eine Frage, welche Struktur „besser” ist – es geht darum, die Datenstruktur auf Ihren Anwendungsfall abzustimmen. Objects bleiben die richtige Wahl für strukturierte Daten mit String-Schlüsseln. Maps handhaben dynamische Schlüssel-Wert-Szenarien sauber. Sets lösen Eindeutigkeitsprobleme effizient.

Verwenden Sie standardmäßig Objects für Einfachheit. Greifen Sie zu Map, wenn Sie dessen spezifische Fähigkeiten benötigen. Nutzen Sie Set, wenn Eindeutigkeit Ihr Hauptanliegen ist.

FAQs

Nicht direkt. JSON.stringify verarbeitet Maps nicht nativ. Sie müssen die Map zuerst in ein Array von Einträgen konvertieren, indem Sie Array.from(map) oder den Spread-Operator verwenden, und dann dieses Array stringifizieren. Um sie wiederherzustellen, parsen Sie das JSON und übergeben das resultierende Array an den Map-Konstruktor: new Map(JSON.parse(jsonString)).

Maps handhaben häufige Einfügungen und Löschungen ohne die Deoptimierung, die das Löschen von Object-Eigenschaften verursachen kann. Sie tracken die Größe nativ mit der size-Eigenschaft, akzeptieren jeden Werttyp als Schlüssel einschließlich DOM-Knoten oder Object-Referenzen und tragen kein Prototype-Pollution-Risiko durch benutzerbereitgestellte Schlüssel.

Diese Methoden werden jetzt in modernen Browsern weitgehend unterstützt. Wenn Sie ältere Umgebungen unterstützen müssen, prüfen Sie Kompatibilitätstabellen oder verwenden Sie ein Polyfill.

Verwenden Sie ein Array, wenn Einfügereihenfolge mit Duplikaten wichtig ist, wenn Sie indexbasierten Zugriff benötigen oder wenn die Collection klein genug ist, dass der Overhead eines Sets nicht gerechtfertigt ist. Für größere Collections, bei denen Eindeutigkeit und schnelle Lookups Priorität haben, ist ein Set die bessere Wahl.

Complete picture for complete understanding

Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Check our GitHub repo and join the thousands of developers in our community.

OpenReplay