Gibt es einen Punkt bei der Verwendung von ES6 Map, an dem alle Tasten Zeichenfolgen sind?

36

Einfache Objektschlüssel müssen Zeichenfolgen sein, wohingegen a MapSchlüssel eines beliebigen Typs haben kann.

Aber ich habe wenig Gebrauch davon in der Praxis. In fast allen Fällen benutze ich trotzdem Strings als Schlüssel. Und vermutlich new Map()ist langsamer als {}. Gibt es noch einen anderen Grund, warum es besser sein könnte, ein Mapstatt eines einfachen Objekts zu verwenden?

Callum
quelle
3
MDN hat wie immer einen guten Vergleich.
Chris Hayes
1
Zu Ihrer Information, die Karte scheint sowohl beim Einstellen als auch beim Abrufen schneller zu sein .
2.
@mpen - jsperf ist jetzt down. Sind Sie sicher map.set('foo', 123)schneller als obj.foo = 123? Wenn ja, ist das sehr überraschend
Callum
@ Callum Uhh..no, nicht positiv. Möglicherweise möchten Sie einige neue Leistungstests schreiben.
Mpen

Antworten:

42

Es gibt einige Gründe, warum ich für die Speicherung von Laufzeitdaten (Caches usw.) lieber Maps als plain objects ( {}) verwende:

  1. Die .sizeEigenschaft teilt mir mit, wie viele Einträge in dieser Karte vorhanden sind.
  2. Die verschiedenen Hilfsmethoden - .clear(), .forEach()usw;
  3. Sie stellen mir standardmäßig Iteratoren zur Verfügung!

Alle anderen Fälle, wie die Übergabe von Funktionsargumenten, das Speichern von Konfigurationen usw., werden mit einfachen Objekten geschrieben.

Denken Sie auch daran: Versuchen Sie nicht, Ihren Code zu früh zu optimieren. Verschwenden Sie nicht Ihre Zeit damit, Benchmarks für einfache Objekte im Vergleich zu Maps durchzuführen, es sei denn, Ihr Projekt leidet unter Leistungsproblemen.

Gustavohenke
quelle
1
Was ist die Identitäts-Hashcode-Funktion, die von Javascript verwendet wird?
Pacerier
1
@ Pacerier ===:)
Gustavohenke
Karten sind heutzutage viel schneller als normale Objekte.
Jayarjo
@gustavohenke Das stimmt nicht. Mapverwendet den SameValueZero-Algorithmus. developer.mozilla.org/en-US/docs/Web/JavaScript/…
lolmaus - Andrey Mikhaylov
@ lolmaus-AndreyMikhaylov okay, aber habe ich etwas über die MapVerwendung dieses oder jenes gesagt ?
Gustavohenke
4

Ich bin mir nicht sicher, aber ich denke, dass die Leistung KEIN Grund ist, Maps zu verwenden. Schauen Sie sich diese aktualisierte jsperf-Seite an:

http://jsperf.com/es6-map-vs-object-properties/73

Es sieht so aus, als wären Objekte (zumindest beim Umgang mit Strings) viel schneller als Maps für die Grundeinstellung und das Abrufen.

starlogodaniel
quelle
2
So schreibt man keine Leistungstests.
Qix
6
So schreibt man keine nützlichen Kommentare. Bitte zögern Sie nicht, dies zu erläutern, wenn Sie eine alternative Methode vorschlagen möchten. Was ist konkret falsch daran, wie diese Tests geschrieben wurden? Sind sie in irgendeiner Weise ungültig oder nicht hilfreich?
Starlogodaniel
9
Sprachsemantik / Konstrukte, die über Mikrobenchmarks getestet werden, dürfen sich nur um eine Variable unterscheiden. Ihre Tests variieren je nach Anzahl der Iterationen, und bei einigen von ihnen wird der Inhalt der inneren Schleife optimiert, da das Ergebnis nicht verwendet wird. Bei einigen Tests werden Variablen vorab deklariert, während bei anderen die Variablendeklaration mit der for-Schleife übereinstimmt - was zu unterschiedlichen Leistungsanomalien führen kann.
Qix
1
Autsch, du hast absolut recht. Zu meiner Verteidigung war meine Version eine Verbesserung gegenüber der vorherigen, aber ich habe sowohl die Vorab-Deklaration als auch die Optimierung des Inhalts der inneren Schleife verpasst. Ich habe mit einem Kollegen zusammengearbeitet, der meinen Entwurf verbessert hat, und ich denke, dass diese Probleme behoben wurden : jsperf.com/es6-map-vs-object-properties/88 . Ich denke jedoch, dass es gültig ist, unterschiedliche Schleifenstile für die unterschiedlichen Datenstrukturen zu haben. Im realen Gebrauch wird die Schleifenstruktur mit der besten Leistung ausgewählt, und Map und Object haben unterschiedliche "optimale" Schleifenstrukturen. Trotzdem danke für den Haken.
Starlogodaniel
Ok, ich verstehe jetzt - früher waren sie langsamer als normale Objekte, wurden aber in den letzten Browsern stark optimiert.
Jayarjo
0

Die anderen Antworten erwähnen keinen letzten Unterschied zwischen Objekten und Maps:

Das MapObjekt enthält Schlüssel-Wert-Paare und speichert die ursprüngliche Einfügereihenfolge der Schlüssel .

Wenn Sie also darüber iterieren, gibt ein Map-Objekt die Schlüssel in der Reihenfolge ihrer Einfügung zurück.

Zitat aus MDN , Hervorhebung von mir


Dies war der Hauptgrund, warum ich mich zum Mapersten Mal für ein Projekt entschieden habe. Ich hatte ein normales Objekt, das ich in einem anzeigen musste <table>, wobei jede Eigenschaft in eine bestimmte Zeile ging.

let productPropertyOrder = [ "name", "weight", "price", "stocked" ];

let product =
{
    name: "Lasagne",
    weight: "1kg",
    price: 10,
    stocked: true
}

Ich habe eine Funktion geschrieben, um ein Objekt Mapgemäß einer gewünschten Tastenreihenfolge in eine umzuwandeln :

function objectToMap( obj, order )
{
    let map = new Map();

    for ( const key of order )
    {
        if ( obj.hasOwnProperty( key ) )
        {
            map.set( key, obj[ key ] );
        }
    }

    return map;
}

Dann könnte die Karte in der gewünschten Reihenfolge durchlaufen werden:

let productMap = objectToMap( product, productPropertyOrder );

for ( const value of productMap.values() )
{
    let cell = document.createElement( "td" );
    cell.innerText = value;
    row.appendChild( cell );
}

Dies ist natürlich ein wenig umständlich, da man es genauso gut anzeigen kann, wenn man die Eigenschaftsreihenfolge durchläuft, ohne dabei eine zu erstellen Map:

for ( const key of productPropertyOrder )
{
    if ( product.hasOwnProperty( key ) )
    {
        let value = product[ key ];
        // create cell
    }
}

Wenn Sie jedoch über eine Reihe solcher Objekte verfügen und diese an vielen Stellen anzeigen möchten, ist es zunächst sinnvoll, sie alle in Karten zu konvertieren.

WD40
quelle