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- unddifference-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.
Discover how at OpenReplay.com.
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.sizevs.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
| Merkmal | Object | Map | Set |
|---|---|---|---|
| Schlüsseltypen | string, symbol | beliebig | N/A (nur Werte) |
| Größe | Object.keys().length | .size | .size |
| Iteration | indirekt | direkt | direkt |
| JSON-Unterstützung | nativ | manuell | manuell |
| Prototype-Risiko | ja | nein | nein |
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.