One place for hosting & domains

      Grundlagen von Map und Set Objects in JavaScript


      Der Autor hat den Open Internet/Free Speech Fund dazu ausgewählt, eine Spende im Rahmen des Programms Write for DOnations zu erhalten.

      In JavaScript verbringen Entwickler oft viel Zeit bei der Entscheidung, welche Datenstruktur sie verwenden sollen. Dies liegt daran, dass die Auswahl der richtigen Datenstruktur die spätere Datenbearbeitung erleichtert, Zeit spart und Code leichter verständlich macht. Die beiden vorherrschenden Datenstrukturen zur Speicherung von Datensammlungen sind Objekte und Arrays (ein Objekttyp). Entwickler verwenden Objekte zum Speichern von Schlüssel/Wert-Paaren und Arrays zum Speichern indizierter Listen. Um Entwicklern jedoch mehr Flexibilität zu geben, hat die Spezifikation ECMAScript 2015 zwei neue Arten von iterierbaren Objekten eingeführt: Maps, d. h. geordnete Sammlungen von Schlüssel/Wert-Paaren, und Sets, d. h. Sammlungen von eindeutigen Werten.

      In diesem Artikel lernen Sie die Objekte Map und Set kennen sowie ihre Ähnlichkeiten oder Unterschiede zu Objekten und Arrays, ihre verfügbaren Eigenschaften und Methoden und Beispiele praktischer Anwendungen.

      Maps

      Eine Map ist eine Sammlung von Schlüssel/Wert-Paaren, die jeden Datentyp als Schlüssel verwenden und die Reihenfolge ihrer Einträge beibehalten kann. Maps haben Elemente von Objekten (ein eindeutiges Schlüssel/Wert-Paar) und Arrays (eine geordnete Sammlung), sie sind jedoch konzeptionell den Objekten ähnlicher. Das liegt daran, dass die Einträge selbst Schlüssel/Wert-Paare wie Objekte sind, obwohl die Größe und Reihenfolge der Einträge wie bei einem Array beibehalten werden.

      Maps können mit der Syntax new Map() initialisiert werden:

      const map = new Map()
      

      Dadurch erhalten Sie eine leere Map:

      Output

      Map(0) {}

      Einer Map Werte hinzufügen

      Mit der Methode set() können Sie einer Map Werte hinzufügen. Das erste Argument ist der Schlüssel und das zweite Argument ist der Wert.

      Das Folgende fügt der map drei Schlüssel/Wert-Paare hinzu:

      map.set('firstName', 'Luke')
      map.set('lastName', 'Skywalker')
      map.set('occupation', 'Jedi Knight')
      

      Hier sehen wir, dass Maps Elemente von Objekten und Arrays haben. Wie bei einem Array haben wir eine nullindizierte Sammlung und wir können auch sehen, wie viele Elemente standardmäßig in der Map sind. Maps verwenden die Syntax => um Schlüssel/Wert-Paare als key => value zu kennzeichnen:

      Output

      Map(3) 0: {"firstName" => "Luke"} 1: {"lastName" => "Skywalker"} 2: {"occupation" => "Jedi Knight"}

      Dieses Beispiel sieht ähnlich wie ein reguläres Object mit Schlüsseln basierend auf Zeichenfolgen aus, aber mit Maps können wir jeden Datentyp als Schlüssel verwenden.

      Zusätzlich zur manuellen Einstellung von Werten auf einer Map können wir eine Map auch bereits mit Werten initialisieren. Das tun wir mit einem Array von Arrays, das zwei Elemente enthält, die jeweils Schlüssel/Wert-Paare sind. Das sieht folgendermaßen aus:

      [ [ 'key1', 'value1'], ['key2', 'value2'] ]
      

      Mit der folgenden Syntax können wir die gleiche Map neu erstellen:

      const map = new Map([
        ['firstName', 'Luke'],
        ['lastName', 'Skywalker'],
        ['occupation', 'Jedi Knight'],
      ])
      

      Anmerkung: In diesem Beispiel werden nachgestellte Kommas – auch nachstehende Kommas genannt – verwendet. Dies ist eine übliche Formatierung bei JavaScript, bei der das letzte Element in einer Reihe ein Komma am Ende hat, wenn eine Sammlung von Daten deklariert wird. Diese Formatierung kann für sauberere diffs und leichtere Code-Bearbeitung gewählt werden, ihre Anwendung ist jedoch optional. Weitere Informationen zu nachgestellten Kommas finden Sie im Artikel Nachgestelltes Komma in den MDN Web-Dokumenten.

      Zufälligerweise ist diese Syntax die gleiche wie das Ergebnis des Aufrufs Object.entries() auf einem Objekt. Das ist eine gebrauchsfertige Möglichkeit, ein Objekt in eine Map umzuwandeln, wie im folgenden Codeblock gezeigt:

      const luke = {
        firstName: 'Luke',
        lastName: 'Skywalker',
        occupation: 'Jedi Knight',
      }
      
      const map = new Map(Object.entries(luke))
      

      Alternativ können Sie mit einer einzelnen Codezeile eine Map wieder in ein Objekt oder ein Array umwandeln.

      Folgendes wandelt eine Map in ein Objekt um:

      const obj = Object.fromEntries(map)
      

      Dadurch ergibt sich der folgende Werte von obj:

      Output

      {firstName: "Luke", lastName: "Skywalker", occupation: "Jedi Knight"}

      Jetzt wandeln wir eine Map in ein Array um:

      const arr = Array.from(map)
      

      Dadurch ergibt sich das folgende Array für arr:

      Output

      [ ['firstName', 'Luke'], ['lastName', 'Skywalker'], ['occupation', 'Jedi Knight'] ]

      Map-Schlüssel

      Maps akzeptieren jeden Datentyp als Schlüssel und lassen das Duplizieren von Schlüsselwerten nicht zu. Zur Veranschaulichung können wir eine Map erstellen und Werte ohne Zeichenfolgen als Schlüssel verwenden sowie zwei Werte dem gleichen Schlüssel zuweisen.

      Zuerst initialisieren wir eine Map mit Schlüsseln ohne Zeichenfolgen:

      const map = new Map()
      
      map.set('1', 'String one')
      map.set(1, 'This will be overwritten')
      map.set(1, 'Number one')
      map.set(true, 'A Boolean')
      

      Dieses Beispiel überschreibt den ersten Schlüssel von 1 mit dem nachfolgenden Schlüssel und behandelt die Zeichenfolge '1' und die Zahl 1 als eindeutige Schlüssel:

      Output

      0: {"1" => "String one"} 1: {1 => "Number one"} 2: {true => "A Boolean"}

      Obwohl viele glauben, dass ein reguläres JavaScript-Objekt bereits mit Zahlen, Booleans und anderen primitiven Datentypen wie Schlüssel umgehen kann, ist das nicht der Fall, da Objekte alle Schlüssel in Zeichenfolgen umändern.

      Initialisieren Sie zum Beispiel ein Objekt mit einem numerischen Schlüssel und vergleichen Sie den Wert mit einem numerischen Schlüssel 1 und einem Zeichenfolgen-Schlüssel "1":

      // Initialize an object with a numerical key
      const obj = { 1: 'One' }
      
      // The key is actually a string
      obj[1] === obj['1']  // true
      

      Das ist der Grund, weshalb stattdessen die Zeichenfolge object Object gedruckt wird, wenn Sie versuchen, ein Objekt als Schlüssel zu verwenden.

      Erstellen Sie zum Beispiel ein Objekt und verwenden Sie es dann als Schlüssel eines anderen Objekts:

      // Create an object
      const objAsKey = { foo: 'bar' }
      
      // Use this object as the key of another object
      const obj = {
        [objAsKey]: 'What will happen?'
      }
      

      Dadurch erhalten Sie Folgendes:

      Output

      {[object Object]: "What will happen?"}

      Dies ist nicht der Fall mit Map. Versuchen Sie, ein Objekt zu erstellen und es als Schlüssel einer Map festzulegen:

      // Create an object
      const objAsKey = { foo: 'bar' }
      
      const map = new Map()
      
      // Set this object as the key of a Map
      map.set(objAsKey, 'What will happen?')
      

      Der key des Map-Elements ist nun das Objekt, das wir erstellt haben.

      Output

      key: {foo: "bar"} value: "What will happen?"

      Folgendes ist bei der Verwendung von Objekt oder Array als Schlüssel wichtig zu beachten: Die Map verwendet zum Vergleich der Gleichheit die Referenz zum Objekt, nicht den Literalwert des Objekts. In JavaScript gibt {} === {} false zurück, da die beiden Objekte nicht die gleichen zwei Objekte sind, obwohl sie den gleichen (leeren) Wert haben.

      Das bedeutet, dass das Hinzufügen von zwei eindeutigen Objekten mit dem gleichen Wert eine Map mit zwei Einträgen erstellt:

      // Add two unique but similar objects as keys to a Map
      map.set({}, 'One')
      map.set({}, 'Two')
      

      Dadurch erhalten Sie Folgendes:

      Output

      Map(2) {{…} => "One", {…} => "Two"}

      Wenn Sie dieselbe Objekt-Referenz zweimal verwenden, wird jedoch eine Map mit einem Eintrag erstellt.

      // Add the same exact object twice as keys to a Map
      const obj = {}
      
      map.set(obj, 'One')
      map.set(obj, 'Two')
      

      Das führt zu Folgendem:

      Output

      Map(1) {{…} => "Two"}

      Das zweite set() aktualisiert den exakt gleichen Schlüssel wie das erste, sodass wir letztendlich eine Map mit nur einem Wert haben.

      Elemente von einer Map abrufen und löschen

      Einer der Nachteile von Objekten ist, dass es schwierig sein kann, diese aufzuzählen oder mit allen Schlüsseln oder Werten zu arbeiten. Die Map-Struktur hat dagegen eine Menge von integrierten Eigenschaften, wodurch man direkter mit ihren Elementen arbeitet kann.

      Wir können eine neue Map initialisieren, um die folgenden Methoden und Eigenschaften zu demonstrieren: delete(), has(), get() und size.

      // Initialize a new Map
      const map = new Map([
        ['animal', 'otter'],
        ['shape', 'triangle'],
        ['city', 'New York'],
        ['country', 'Bulgaria'],
      ])
      

      Verwenden Sie die Methode has(), um das Vorhandensein eines Elements in einer Map zu überprüfen. has() gibt ein Boolean zurück.

      // Check if a key exists in a Map
      map.has('shark') // false
      map.has('country') // true
      

      Verwenden Sie die Methode get(), um mit einem Schlüssel einen Wert abzurufen.

      // Get an item from a Map
      map.get('animal') // "otter"
      

      Ein besonderer Vorteil von Maps gegenüber Objekten ist, dass Sie jederzeit die Größe einer Map finden können, so wie es bei einem Array möglich ist. Die Anzahl der Elemente in einer Map können Sie mit der Eigenschaft size abrufen. Dies beinhaltet weniger Schritte als die Umwandlung eines Objekts in ein Array, um die length zu finden.

      // Get the count of items in a Map
      map.size // 4
      

      Verwenden Sie die Methode delete(), um ein Element mithilfe eines Schlüssels von einer Map zu entfernen. Die Methode gibt ein Boolean true zurück, wenn ein Element vorhanden war und gelöscht wurde, und false, wenn es mit keinem Element übereinstimmt.

      // Delete an item from a Map by key
      map.delete('city') // true
      

      Dadurch ergibt sich folgende Map:

      Output

      Map(3) {"animal" => "otter", "shape" => "triangle", "country" => "Bulgaria"}

      Zu guter Letzt können alle Werte in einer Map mit map.clear() gelöscht werden.

      // Empty a Map
      map.clear()
      

      Dadurch erhalten Sie Folgendes:

      Output

      Map(0) {}

      Schlüssel, Werte und Einträge für Maps

      Objekte können Schlüssel, Werte und Einträge abrufen, indem sie die Eigenschaften des Objekt-Konstruktors verwenden. Maps hingegen haben Prototyp-Methoden, die es uns ermöglichen, die Schlüssel, Werte und Einträge der Map-Instanz direkt abzurufen.

      Die Methoden keys()​​​, values() und entries() geben alle einen MapIterator zurück, der insofern einem Array ähnlich ist, als Sie for...of verwenden können, um die Werte zu durchlaufen.

      Hier ist ein weiteres Beispiel einer Map, die wir zur Demonstration dieser Methoden verwenden können:

      const map = new Map([
        [1970, 'bell bottoms'],
        [1980, 'leg warmers'],
        [1990, 'flannel'],
      ])
      

      Die Methode keys() gibt die Schlüssel zurück:

      map.keys()
      

      Output

      MapIterator {1970, 1980, 1990}

      Die Methode values() gibt die Werte zurück:

      map.values()
      

      Output

      MapIterator {"bell bottoms", "leg warmers", "flannel"}

      Die Methode entries() gibt ein Array von Schlüssel/Wert-Paaren zurück:

      map.entries()
      

      Output

      MapIterator {1970 => "bell bottoms", 1980 => "leg warmers", 1990 => "flannel"}

      Iteration mit Map

      Map verfügt – ähnlich wie bei einem Array – über eine integrierte forEach-Methode für die integrierte Iteration. Worüber sie iterieren, unterscheidet sich jedoch ein wenig. Das Callback von forEach einer Map iteriert über value, key und die map selbst, während die Array-Version über item, index und das array selbst iteriert.

      // Map
      Map.prototype.forEach((value, key, map) = () => {})
      
      // Array
      Array.prototype.forEach((item, index, array) = () => {})
      

      Das ist ein großer Vorteil für Maps gegenüber Objekten, da Objekte mit keys(), values() oder entries() umgewandelt werden müssen und es keinen einfachen Weg gibt, die Eigenschaften eines Objekts ohne Umwandlung abzurufen.

      Um dies zu demonstrieren, iterieren wir über unsere Map und protokollieren die Schlüssel/Wert-Paare in der Konsole:

      // Log the keys and values of the Map with forEach
      map.forEach((value, key) => {
        console.log(`${key}: ${value}`)
      })
      

      Dies ergibt:

      Output

      1970: bell bottoms 1980: leg warmers 1990: flannel

      Da eine for...of-Schleife über Iterablen wie Map und Array iteriert, können wir durch Destrukturierung des Arrays der Map-Elemente genau das gleiche Ergebnis erhalten.

      // Destructure the key and value out of the Map item
      for (const [key, value] of map) {
        // Log the keys and values of the Map with for...of
        console.log(`${key}: ${value}`)
      }
      

      Eigenschaften und Methoden von Map

      Die folgende Tabelle zeigt eine Liste der Eigenschaften und Methoden von Map für einen schnellen Überblick:

      Eigenschaften/Methoden Beschreibung Rückgabe
      set(key, value) Hängt einer Map ein Schlüssel/Wert-Paar an Map-Objekt
      delete(key) Entfernt ein Schlüssel/Wert-Paar von einer Map mithilfe eines Schlüssels Boolean
      get(key) Gibt einen Wert mithilfe eines Schlüssels zurück Wert
      has(key) Überprüft das Vorhandensein eines Elements in einer Map mithilfe eines Schlüssels Boolean
      clear() Entfernt alle Elemente von einer Map N/A
      keys() Gibt alle Schlüssel in einer Map zurück MapIterator-Objekt
      values() Gibt alle Werte in einer Map zurück MapIterator-Objekt
      entries() Gibt alle Schlüssel und Werte in einer Map als [key, value] zurück MapIterator-Objekt
      forEach() Iteriert über die Map in der Reihenfolge der Einfügungen N/A
      size Gibt die Anzahl der Elemente in einer Map zurück Zahl

      Wann man Map verwendet

      Zusammengefasst kann man sagen: Maps sind insofern Objekten ähnlich, als sie Schlüssel/Wert-Paare enthalten, aber Maps haben mehrere Vorteile gegenüber Objekten:

      • Size – Maps haben die Eigenschaft size, während Objekte keine integrierte Möglichkeit zum Abruf ihrer Größe haben.
      • Iteration – Maps sind direkt iterierbar, Objekte nicht.
      • Flexibilität – Maps können einen beliebigen Datentyp (primitiv oder Objekt) als Schlüssel für einen Wert haben, während Objekte nur Zeichenfolgen haben können.
      • Geordnet – Maps behalten die Reihenfolge ihrer Einfügungen bei, während Objekte keine garantierte Reihenfolge haben.

      Aufgrund dieser Faktoren sind Maps eine leistungsstarke Datenstruktur, die in Betracht gezogen werden sollte. Objekte haben jedoch auch einige wichtige Vorteile:

      • JSON – Objekte funktionieren einwandfrei mit JSON.parse() und JSON.stringify(), zwei wesentliche Funktionen zum Arbeiten mit JSON, einem gängigen Datenformat, mit dem viele REST-APIs zu tun haben.
      • Mit einem einzelnen Element arbeiten – Wenn Sie mit einem bekannten Wert in einem Objekt arbeiten, können Sie direkt mit dem Schlüssel darauf zugreifen, ohne eine Methode wie Maps get() verwenden zu müssen.

      Das hilft Ihnen bei der Entscheidung, ob Map oder Objekt die richtige Datenstruktur für Ihren Anwendungsfall ist.

      Set

      Ein Set ist eine Sammlung von eindeutigen Werten. Im Gegensatz zu einer Map ist ein Set einem Array konzeptionell ähnlicher als einem Objekt, da es eine Liste von Werten und nicht Schlüssel/Wert-Paaren ist. Set ist jedoch kein Ersatz für Arrays, sondern eine Ergänzung für die zusätzliche Unterstützung der Arbeit mit duplizierten Daten.

      Sie können Sets mit der Syntax new Set() initialisieren.

      const set = new Set()
      

      Dadurch erhalten Sie ein leeres Set:

      Output

      Set(0) {}

      Elemente können einem Set mit der Methode add() hinzugefügt werden. (Das darf nicht mit der Methode set() für Map verwechselt werden, obwohl sie ähnlich ist.)

      // Add items to a Set
      set.add('Beethoven')
      set.add('Mozart')
      set.add('Chopin')
      

      Nachdem Sets nur eindeutige Werte enthalten können, wird jeder Versuch, einen bereits vorhandenen Wert hinzuzufügen, ignoriert.

      set.add('Chopin') // Set will still contain 3 unique values
      

      Anmerkung: Derselbe Gleichheits-Vergleich, der für Map-Schlüssel gilt, gilt auch für Set-Elemente. Zwei Objekte, die den gleichen Wert haben, aber nicht die gleiche Referenz teilen, werden nicht als gleich angesehen.

      Sie können Sets auch mit einem Array von Werten initialisieren. Wenn im Array doppelte Werte vorhanden sind, werden sie vom Set entfernt.

      // Initialize a Set from an Array
      const set = new Set(['Beethoven', 'Mozart', 'Chopin', 'Chopin'])
      

      Output

      Set(3) {"Beethoven", "Mozart", "Chopin"}

      Umgekehrt kann ein Set mit einer Code-Zeile in ein Array umgewandelt werden:

      const arr = [...set]
      

      Output

      (3) ["Beethoven", "Mozart", "Chopin"]

      Set hat viele gleiche Methoden und Eigenschaften wie Map, einschließlich delete(),​has(), clear() und size.

      // Delete an item
      set.delete('Beethoven') // true
      
      // Check for the existence of an item
      set.has('Beethoven') // false
      
      // Clear a Set
      set.clear()
      
      // Check the size of a Set
      set.size // 0
      

      Beachten Sie, dass Set keine Möglichkeit hat, auf einen Wert über einen Schlüssel oder einen Index zuzugreifen, wie Map.get(key) oder arr[index].

      Schlüssel, Werte und Einträge für Sets

      Map und Set haben beide die Methoden keys(), values() und entries(), die einen Iterator zurückgeben. Bei Map hat jede dieser Methoden ihren eigenen Zweck. Sets haben jedoch keine Schlüssel und daher sind Schlüssel ein Alias für Werte. Das bedeutet, dass keys() und values() beide den gleichen Iterator zurückgeben und entries() den Wert zweimal zurückgeben. Es ist am sinnvollsten, nur values() mit Set zu verwenden, da die beiden anderen Methoden der Einheitlichkeit und übergreifenden Kompatibilität mit Map dienen.

      const set = new Set([1, 2, 3])
      // Get the values of a set
      set.values()
      

      Output

      SetIterator {1, 2, 3}

      Iteration mit Set

      Wie Map hat auch Set eine integrierte forEach()-Methode. Da Sets keine Schlüssel haben, geben der erste und der zweite Parameter des forEach()-Callbacks den gleichen Wert zurück, sodass es dafür keinen Anwendungsfall außerhalb der Kompatibilität mit Map gibt. Die Parameter von forEach() sind (value, key, set).

      Sowohl forEach() als auch for...of können für Set verwendet werden. Sehen wir uns zuerst die Iteration forEach() an:

      const set = new Set(['hi', 'hello', 'good day'])
      
      // Iterate a Set with forEach
      set.forEach((value) => console.log(value))
      

      Dann können wir die Version for...of schreiben:

      // Iterate a Set with for...of
      for (const value of set) {  
          console.log(value);
      }
      

      Beide Strategien ergeben Folgendes:

      Output

      hi hello good day

      Eigenschaften und Methoden von Set

      Die folgende Tabelle zeigt eine Liste der Eigenschaften und Methoden von Set für einen schnellen Überblick:

      Eigenschaften/Methoden Beschreibung Rückgabe
      add(value) Hängt einem Set ein neues Element an Set-Objekt
      delete(value) Entfernt das angegebene Element von einem Set Boolean
      has() Überprüft, ob ein Element in einem Set vorhanden ist Boolean
      clear() Entfernt alle Elemente von einem Set N/A
      keys() Gibt alle Werte eines Sets zurück (genau wie values()) SetIterator-Objekt
      values() Gibt alle Werte eines Sets zurück (genau wie keys()) SetIterator-Objekt
      entries() Gibt alle Werte eines Sets als [value, value] zurück SetIterator-Objekt
      forEach() Iteriert über das Set in der Reihenfolge der Einfügungen N/A
      size Gibt die Anzahl der Elemente eines Sets zurück Zahl

      Wann man Set verwendet

      Set ist eine nützliche Ergänzung zu Ihrem JavaScript-Toolkit, insbesondere für die Arbeit mit doppelten Werten in Daten.

      In einer einzelnen Zeile können wir ein neues Array ohne doppelte Werte eines Arrays, das doppelte Werte hat, erstellen.

      const uniqueArray = [ ...new Set([1, 1, 2, 2, 2, 3])] // (3) [1, 2, 3]
      

      Dies ergibt:

      Output

      (3) [1, 2, 3]

      Set kann verwendet werden, um nach Union, Intersection und Difference zwischen zwei Datensätzen zu suchen. Arrays haben Sets gegenüber jedoch den erheblichen Vorteil der zusätzlichen Datenmanipulation aufgrund der Methoden sort(), map(), filter() und reduce() sowie der direkten Kompatibilität mit JSON-Methoden.

      Zusammenfassung

      In diesem Artikel haben Sie gelernt, dass eine Map eine Sammlung von geordneten Schlüssel/Wert-Paaren und ein Set eine Sammlung von eindeutigen Werten ist. Beide Datenstrukturen fügen JavaScript zusätzliche Fähigkeiten hinzu und vereinfachen jeweils gängige Aufgaben wie das Auffinden der Länge eines Schlüssel/Wertpaares und das Entfernen doppelter Elemente aus einem Datensatz. Andererseits werden Objekte und Arrays traditionell für die Datenspeicherung und -Bearbeitung in JavaScript verwendet und haben direkte Kompatibilität mit JSON, wodurch sie weiterhin die wichtigsten Datenstrukturen bleiben, insbesondere für die Arbeit mit REST-APIs. Maps und Sets sind in erster Linie nützlich als unterstützende Datenstrukturen für Objekte und Arrays.

      Wenn Sie mehr über JavaScript erfahren möchten, besuchen Sie unsere Homepage für unsere Reihe So codieren Sie in JavaScript oder durchsuchen Sie unsere Reihe So codieren Sie in Node.js für Artikel über Back-End-Entwicklung.



      Source link

      Comprendre les objects Map et Set en JavaScript


      L’auteur a choisi le Open Internet/Free Speech Fund comme récipiendaire d’un don dans le cadre du programme Write for Donations.

      En JavaScript, les développeurs passent souvent beaucoup de temps à décider de la structure de données correcte à utiliser. En effet, le choix de la bonne structure de données peut faciliter la manipulation ultérieure de ces données, ce qui permet de gagner du temps et de rendre le code plus facile à comprendre. Les deux structures de données prédominantes pour le stockage des collections de données sont Objets et Tableaux (un type d’objet). Les développeurs utilisent des Objets pour stocker les paires clé/valeur et des Tableaux pour stocker les listes indexées. Toutefois, pour donner plus de flexibilité aux développeurs, la spécification ECMAScript 2015 a introduit deux nouveaux types d’objets itératifs : les objets Map, qui sont des collections ordonnées de paires clé/valeur, et les objets Set, qui sont des collections de valeurs uniques.

      Dans cet article, vous passerez en revue les objets Map et Set, ce qui les rend similaires ou différents des Objets et des Tableaux, les propriétés et méthodes dont ils disposent, et des exemples d’utilisations pratiques.

      Objets Map

      Un objet Map est une collection de paires clé/valeur qui peut utiliser n’importe quel type de données comme clé et peut maintenir l’ordre de ses entrées. Les objets Map comportent des éléments d’Objets (une collection unique de paires clé/valeur) et de Tableaux (une collection ordonnée), mais sont plus proches des Objets sur le plan conceptuel. En effet, bien que la taille et l’ordre des entrées soient préservés comme un Tableau, les entrées elles-mêmes sont des paires clé/valeur comme les Objets.

      Les objets Map peuvent être initialisés avec la nouvelle syntaxe Map() :

      const map = new Map()
      

      Cela nous donne un objet Map vide :

      Output

      Map(0) {}

      Ajout de valeurs à un objet Map

      Vous pouvez ajouter des valeurs à un objet Map avec la méthode set(). Le premier argument sera la clé, et le second la valeur.

      Ce qui suit ajoute trois paires clé/valeur à l’objet Map :

      map.set('firstName', 'Luke')
      map.set('lastName', 'Skywalker')
      map.set('occupation', 'Jedi Knight')
      

      Ici, nous commençons à voir comment les objets Map possèdent à la fois des éléments d’Objets et de Tableaux. Comme dans un Tableau, nous avons une collection indexée à zéro, et nous pouvons également voir combien d’éléments se trouvent par défaut dans l’objet Map. Les objets Map utilisent la syntaxe => pour signifier les paires clé/valeur en tant que key => value :

      Output

      Map(3) 0: {"firstName" => "Luke"} 1: {"lastName" => "Skywalker"} 2: {"occupation" => "Jedi Knight"}

      Cet exemple ressemble à un objet ordinaire avec des clés en chaîne, mais nous pouvons utiliser n’importe quel type de données comme clé avec des objets Map.

      Outre la définition manuelle de valeurs sur un objet Map, nous pouvons également initialiser un objet Map avec des valeurs existantes. Pour ce faire, nous utilisons un Tableau des Tableaux contenant deux éléments qui représentent chacun une paire clé/valeur ; ce tableau ressemble à ceci :

      [ [ 'key1', 'value1'], ['key2', 'value2'] ]
      

      En utilisant la syntaxe suivante, nous pouvons recréer le même objet Map :

      const map = new Map([
        ['firstName', 'Luke'],
        ['lastName', 'Skywalker'],
        ['occupation', 'Jedi Knight'],
      ])
      

      Remarque : cet exemple utilise des virgules de fin de ligne, également appelées “dangling commas”. Il s’agit d’une pratique de formatage JavaScript dans laquelle le dernier élément d’une série lors de la déclaration d’un ensemble de données comporte une virgule finale. Bien que ce choix de formatage puisse être utilisé pour des différences plus nettes et une manipulation plus facile du code, son utilisation ou non est une question de préférence. Pour plus d’informations sur les virgules de fin de ligne, consultez cet article sur les virgules de fin de ligne dans les documents web de MDN.

      Soit dit en passant, cette syntaxe est la même que celle qui résulte de l’appel de Object.entries() sur un Objet. Cela permet de convertir un Objet en un objet Map, comme le montre le bloc de code suivant :

      const luke = {
        firstName: 'Luke',
        lastName: 'Skywalker',
        occupation: 'Jedi Knight',
      }
      
      const map = new Map(Object.entries(luke))
      

      Vous pouvez également transformer un objet Map en un Objet ou un Tableau avec une seule ligne de code.

      Ce qui suit permet de convertir un objet Map en Objet :

      const obj = Object.fromEntries(map)
      

      Il en résultera la valeur suivante de obj :

      Output

      {firstName: "Luke", lastName: "Skywalker", occupation: "Jedi Knight"}

      Maintenant, convertissons un objet Map en Tableau :

      const arr = Array.from(map)
      

      Il en résultera le tableau suivant pour arr :

      Output

      [ ['firstName', 'Luke'], ['lastName', 'Skywalker'], ['occupation', 'Jedi Knight'] ]

      Clés d’objet Map

      Les objets Map acceptent tout type de données comme clé, et n’autorisent pas la duplication des valeurs de la clé. Nous pouvons le démontrer en créant un objet Map et en utilisant des valeurs non linéaires comme clés, ainsi qu’en attribuant deux valeurs à la même clé.

      Tout d’abord, initialisons une carte avec des clés non ordonnées :

      const map = new Map()
      
      map.set('1', 'String one')
      map.set(1, 'This will be overwritten')
      map.set(1, 'Number one')
      map.set(true, 'A Boolean')
      

      Cet exemple remplacera la première clé de 1 par la suivante, et traitera "1" la chaîne et 1 le chiffre comme des clés uniques :

      Output

      0: {"1" => "String one"} 1: {1 => "Number one"} 2: {true => "A Boolean"}

      Bien qu’il soit communément admis qu’un objet JavaScript ordinaire peut déjà traiter des nombres, des booléens et d’autres types de données primitives comme des clés, ce n’est en fait pas le cas, car les objets changent toutes les clés en chaînes de caractères.

      À titre d’exemple, initialisez un objet avec une clé numérique et comparez la valeur d’une clé numérique 1 et d’une clé "1" en chaîne :

      // Initialize an object with a numerical key
      const obj = { 1: 'One' }
      
      // The key is actually a string
      obj[1] === obj['1']  // true
      

      C’est pourquoi si vous essayez d’utiliser un objet comme clé, il imprimera la chaîne de caractères Objet à la place.

      Par exemple, créez un Objet et utilisez-le ensuite comme clé d’un autre Objet :

      // Create an object
      const objAsKey = { foo: 'bar' }
      
      // Use this object as the key of another object
      const obj = {
        [objAsKey]: 'What will happen?'
      }
      

      Il en résultera ce qui suit :

      Output

      {[object Object]: "What will happen?"}

      Ce n’est pas le cas avec un objet Map. Essayez de créer un Objet et de le définir comme la clé d’un objet Map :

      // Create an object
      const objAsKey = { foo: 'bar' }
      
      const map = new Map()
      
      // Set this object as the key of a Map
      map.set(objAsKey, 'What will happen?')
      

      La key de l’élément Map est maintenant l’objet que nous avons créé.

      Output

      key: {foo: "bar"} value: "What will happen?"

      Il y a une chose importante à noter concernant l’utilisation d’un Objet ou d’un Tableau comme clé : l’objet Map utilise la référence à l’Objet pour comparer l’égalité, et non la valeur littérale de l’Objet. En JavaScript {} === {} renvoie false (faux), car les deux Objets ne sont pas les mêmes deux Objets, bien qu’ayant la même valeur (vide).

      Cela signifie que l’ajout de deux Objets uniques ayant la même valeur créera un objet Map à deux entrées :

      // Add two unique but similar objects as keys to a Map
      map.set({}, 'One')
      map.set({}, 'Two')
      

      Il en résultera ce qui suit :

      Output

      Map(2) {{…} => "One", {…} => "Two"}

      Mais en utilisant deux fois la même référence d’Objet, on crée un objet Map avec une seule entrée.

      // Add the same exact object twice as keys to a Map
      const obj = {}
      
      map.set(obj, 'One')
      map.set(obj, 'Two')
      

      Ce qui donnera le résultat suivant :

      Output

      Map(1) {{…} => "Two"}

      Le second set() met à jour exactement la même clé que le premier, de sorte que nous nous retrouvons avec un objet Map qui n’a qu’une seule valeur.

      Ajout et suppression d’éléments d’un objet Map

      L’un des inconvénients du travail avec les Objets est qu’il peut être difficile de les énumérer, ou de travailler avec toutes les clés ou valeurs. La structure de l’objet Map, en revanche, possède de nombreuses propriétés intégrées qui rendent le travail avec leurs éléments plus direct.

      Nous pouvons initialiser un nouvel objet Map pour démontrer les méthodes et propriétés suivantes : delete(), has(), get(), et size.

      // Initialize a new Map
      const map = new Map([
        ['animal', 'otter'],
        ['shape', 'triangle'],
        ['city', 'New York'],
        ['country', 'Bulgaria'],
      ])
      

      Utilisez la méthode has() pour vérifier l’existence d’un élément dans un objet Map. has() renverra un booléen.

      // Check if a key exists in a Map
      map.has('shark') // false
      map.has('country') // true
      

      Utilisez la méthode get() pour récupérer une valeur par clé.

      // Get an item from a Map
      map.get('animal') // "otter"
      

      L’un des avantages particuliers des objets Map par rapport aux Objets est que vous pouvez trouver la taille d’un objet Map à tout moment, comme vous le feriez avec un Tableau. Vous pouvez obtenir le nombre d’articles dans un objet Map avec la propriété size. Cela implique moins d’étapes que la conversion d’un Objet en Tableau pour en déterminer la longueur.

      // Get the count of items in a Map
      map.size // 4
      

      Utilisez la méthode delete() pour supprimer un élément d’un objet Map par clé. La méthode retournera un booléen-true (vrai) si un élément existait et a été supprimé, et false (faux) s’il ne correspondait à aucun élément.

      // Delete an item from a Map by key
      map.delete('city') // true
      

      Il en résultera la carte suivante :

      Output

      Map(3) {"animal" => "otter", "shape" => "triangle", "country" => "Bulgaria"}

      Enfin, un objet Map peut être débarrassé de toutes ses valeurs avec map.clear().

      // Empty a Map
      map.clear()
      

      Il en résultera :

      Output

      Map(0) {}

      Clés, Valeurs et Entrées pour objets Map

      Les objets peuvent récupérer des clés, des valeurs et des entrées en utilisant les propriétés du constructeur d'Objet. Les objets Map, en revanche, disposent de méthodes prototypes qui nous permettent d’obtenir directement les clés, les valeurs et les entrées de l’instance de l’objet Map.

      Les méthodes keys(), values(), et entries() renvoient toutes un MapIterator, qui est similaire à un Tableau en ce sens que vous pouvez utiliser for...of pour boucler les valeurs.

      Voici un autre exemple d’objet Map, que nous pouvons utiliser pour démontrer ces méthodes :

      const map = new Map([
        [1970, 'bell bottoms'],
        [1980, 'leg warmers'],
        [1990, 'flannel'],
      ])
      

      La méthode keys() renvoie les clés :

      map.keys()
      

      Output

      MapIterator {1970, 1980, 1990}

      La méthode values() renvoie les valeurs :

      map.values()
      

      Output

      MapIterator {"bell bottoms", "leg warmers", "flannel"}

      La méthode entries() renvoie un tableau de paires clé/valeur :

      map.entries()
      

      Output

      MapIterator {1970 => "bell bottoms", 1980 => "leg warmers", 1990 => "flannel"}

      Itération avec objet Map

      Map dispose d’une méthode forEach intégrée, similaire à celle d’un Tableau, pour l’itération intégrée. Cependant, il y a une petite différence dans ce qu’ils répètent. Le rappel du forEach d’un objet Map se fait par la value, la key et l’objet Map lui-même, tandis que la version Tableau se fait par l’élément, l’index et le tableau lui-même.

      // Map
      Map.prototype.forEach((value, key, map) = () => {})
      
      // Array
      Array.prototype.forEach((item, index, array) = () => {})
      

      C’est un grand avantage pour les objets Map par rapport aux Objets, car les Objets doivent être convertis avec keys(), values() ou entries(), et il n’y a pas de moyen simple de récupérer les propriétés d’un Objet sans le convertir.

      Pour le démontrer, parcourons notre objet Map et enregistrons les paires clé/valeur sur la console :

      // Log the keys and values of the Map with forEach
      map.forEach((value, key) => {
        console.log(`${key}: ${value}`)
      })
      

      Il en résultera :

      Output

      1970: bell bottoms 1980: leg warmers 1990: flannel

      Comme une boucle for...of se réitère sur des itérables comme objet Map et Tableau, nous pouvons obtenir exactement le même résultat en déstructurant l’ensemble des éléments de l’objet Map :

      // Destructure the key and value out of the Map item
      for (const [key, value] of map) {
        // Log the keys and values of the Map with for...of
        console.log(`${key}: ${value}`)
      }
      

      Propriétés et méthodes Map

      Le tableau suivant présente une liste des propriétés et des méthodes Map pour une consultation rapide :

      Propriétés/Méthodes Description Retours
      set(key, value) Ajoute une paire clé/valeur à une carte Objet Map
      delete(key) Supprime une paire clé/valeur d’un objet Map par clé Booléen
      get(key) Retourne une valeur par clé valeur
      has(key) Recherche la présence d’un élément dans un objet Map par clé Booléen
      clear() Supprime tous les éléments d’un objet Map S/O
      keys() Retourne toutes les clés dans un objet Map Objet MapIterator
      values() Retourne toutes les valeurs dans un objet Map Objet MapIterator
      entries() Retourne toutes les clés et valeurs dans un objet Map sous forme de [key, valeur] Objet MapIterator
      forEach() Se réitère dans l’objet Map dans l’ordre d’insertion S/O
      size Retourne le nombre d’items dans un objet Map Number

      Quand utiliser Map

      En résumé, les objets Map sont similaires aux Objets dans la mesure où ils contiennent des paires clé/valeur, mais les objets Map présentent plusieurs avantages par rapport aux Objets :

      • Taille – Les objets Map ont une propriété size, alors que les Objets n’ont pas de moyen intégré pour récupérer leur taille.
      • Itération – Les objets Map sont directement itérables alors que les Objets ne le sont pas.
      • Flexibilité – Les objets Map peuvent avoir n’importe quel type de données (primitives ou Objets) comme clé pour une valeur, alors que les Objets ne peuvent avoir que des chaînes de caractères.
      • Ordonné – Les objets Map conservent leur ordre d’insertion, alors que les Objets n’ont pas d’ordre garanti.

      En raison de ces facteurs, les objets Map constituent une structure de données puissante à prendre en compte. Cependant, les Objets présentent également des avantages importants :

      • JSON – Les Objets fonctionnent parfaitement avec JSON.parse() et JSON.stringify(), deux fonctions essentielles pour travailler avec JSON, un format de données commun que de nombreuses REST API traitent.
      • Travailler avec un seul élément – En travaillant avec une valeur connue dans un Objet, vous pouvez y accéder directement avec la clé sans avoir besoin d’utiliser une méthode, telle que get() d’objet Map.

      Cette liste vous aidera à décider si un objet Map ou un Objet est la bonne structure de données pour votre cas d’utilisation.

      Objet Set

      Un objet Set est une collection de valeurs uniques. Contrairement à un objet Map, un objet Set est conceptuellement plus proche d’un Tableau que d’un Objet, puisqu’il s’agit d’une liste de valeurs et non de paires clé/valeur. Toutefois, l’objet Set ne remplace pas les Tableaux, mais constitue plutôt un complément pour fournir un soutien supplémentaire pour le travail avec des données dupliquées.

      Vous pouvez initialiser les objets Set avec la nouvelle syntaxe Set().

      const set = new Set()
      

      Cela nous donne un objet Set vide :

      Output

      Set(0) {}

      Les éléments peuvent être ajoutés à un objet Set avec la méthode add(). (À ne pas confondre avec la méthode set() disponible pour Map, bien qu’elles soient similaires).

      // Add items to a Set
      set.add('Beethoven')
      set.add('Mozart')
      set.add('Chopin')
      

      Comme les objets Set ne peuvent contenir que des valeurs uniques, toute tentative d’ajouter une valeur qui existe déjà sera ignorée.

      set.add('Chopin') // Set will still contain 3 unique values
      

      Note : la même comparaison d’égalité qui s’applique aux clés Map s’applique aux items Set. Deux objets qui ont la même valeur mais ne partagent pas la même référence ne seront pas considérés comme égaux.

      Vous pouvez également initialiser les objets Set avec un Tableau de valeurs. S’il y a des valeurs en double dans le tableau, elles seront supprimées de l’objet Set.

      // Initialize a Set from an Array
      const set = new Set(['Beethoven', 'Mozart', 'Chopin', 'Chopin'])
      

      Output

      Set(3) {"Beethoven", "Mozart", "Chopin"}

      Inversement, un objet Set peut être converti en un Tableau avec une ligne de code :

      const arr = [...set]
      

      Output

      (3) ["Beethoven", "Mozart", "Chopin"]

      Set possède un grand nombre de méthodes et de propriétés identiques à celles de Map, notamment delete(), has(), clear() et size.

      // Delete an item
      set.delete('Beethoven') // true
      
      // Check for the existence of an item
      set.has('Beethoven') // false
      
      // Clear a Set
      set.clear()
      
      // Check the size of a Set
      set.size // 0
      

      Notez que Set n’a pas de moyen d’accéder à une valeur par une clé ou un index, comme Map.get(key) ou arr[index].

      Clés, Valeurs et Entrées pour objets Set

      Map et Set ont tous deux des méthodes keys(), values(), et entries() qui renvoient un itérateur. Cependant, si chacune de ces méthodes a un but distinct dans Map, les objets Set n’ont pas de clés, et les clés sont donc un alias pour les valeurs. Cela signifie que keys() et values() renverront toutes deux le même itérateur, et que entries() renverra la valeur deux fois. Il est plus logique de n’utiliser que des values() avec Set, car les deux autres méthodes existent pour la cohérence et la compatibilité croisée avec Map.

      const set = new Set([1, 2, 3])
      // Get the values of a set
      set.values()
      

      Output

      SetIterator {1, 2, 3}

      Itération avec Set

      Comme Map, Set a une méthode intégrée forEach(). Comme les objets Set n’ont pas de clés, le premier et le second paramètre du rappel forEach() renvoient la même valeur, il n’y a donc pas de cas d’utilisation en dehors de la compatibilité avec Map. Les paramètres de forEach() sont (value, key, set).

      forEach() et for...of peuvent tous deux être utilisés sur Set. Tout d’abord, examinons l’itération forEach() :

      const set = new Set(['hi', 'hello', 'good day'])
      
      // Iterate a Set with forEach
      set.forEach((value) => console.log(value))
      

      Ensuite, nous pouvons écrire la version for...of :

      // Iterate a Set with for...of
      for (const value of set) {  
          console.log(value);
      }
      

      Ces deux stratégies donneront les résultats suivants :

      Output

      hi hello good day

      Propriétés et méthodes de Set

      Le tableau suivant présente une liste des propriétés et des méthodes de Set pour une consultation rapide :

      Propriétés/Méthodes Description Retours
      add(value) Ajoute un nouvel élément à un objet Set Objet Set
      delete(value) Supprime l’élément spécifié d’un objet Set Booléen
      has() Recherche la présence d’un item dans un objet Set Booléen
      clear() Supprime tous les éléments d’un objet Set S/O
      keys() Renvoie toutes les valeurs d’un objet Set (identique à values()) Objet SetIterator
      values() Renvoie toutes les valeurs d’un objet Set (identique à values() Objet SetIterator
      entries() Retourne toutes les valeurs d’un objet Set comme [value, value] Objet SetIterator
      forEach() Se réitère dans l’objet Set dans l’ordre d’insertion S/O
      size Retourne le nombre d’items de l’objet Set Number

      Quand utiliser Set

      Set est un complément utile à votre boîte à outils JavaScript, en particulier pour travailler avec des valeurs doubles dans les données.

      En une seule ligne, nous pouvons créer un nouveau Tableau sans valeurs doubles à partir d’un Tableau qui a des valeurs doubles.

      const uniqueArray = [ ...new Set([1, 1, 2, 2, 2, 3])] // (3) [1, 2, 3]
      

      Il en résultera :

      Output

      (3) [1, 2, 3]

      Set peut être utilisé pour trouver l’union, l’intersection et la différence entre deux ensembles de données. Toutefois, les Tableaux présentent un avantage significatif par rapport aux objets Set pour la manipulation supplémentaire des données en raison des méthodes sort(), map(), filter() et reduce(), ainsi que de la compatibilité directe avec les méthodes JSON.

      Conclusion

      Dans cet article, vous avez appris qu’un objet Map est une collection de paires de clés/valeurs ordonnées, et qu’un objet Set est une collection de valeurs uniques. Ces deux structures de données ajoutent des capacités supplémentaires à JavaScript et simplifient les tâches courantes telles que la recherche de la longueur d’une collection de paires clé/valeur et la suppression des éléments en double d’un ensemble de données, respectivement. D’autre part, les Objets et les Tableaux ont été traditionnellement utilisés pour le stockage et la manipulation de données en JavaScript, et sont directement compatibles avec JSON, ce qui continue à en faire les structures de données les plus essentielles, notamment pour travailler avec les REST API. Les objets Map et Set sont principalement utiles comme structures de données de soutien pour les Objets et les Tableaux.

      Si vous souhaitez en savoir plus sur JavaScript, consultez la page d’accueil de notre série Comment coder en JavaScript, ou parcourez notre série Comment coder en Node.js pour lire des articles sur le développement back-end.



      Source link

      Entendendo os objetos Map e Conjunto no JavaScript


      O autor selecionou a Open Internet/Free Speech Fund para receber uma doação como parte do programa Write for DOnations.

      No JavaScript, os desenvolvedores geralmente gastam bastante tempo decidindo a estrutura de dados correta a ser usada. Isso acontece porque escolher a estrutura de dados correta pode facilitar a manipulação desses dados mais tarde, economizando tempo e facilitando a compreensão do código. As duas estruturas de dados predominantes para armazenar coleções de dados são Objetos e Matrizes (um tipo de objeto). Os desenvolvedores usam os Obejtos para armazenar pares de chave-valor e Matrizes para armazenar listas indexadas. No entanto, para dar maior flexibilidade aos desenvolvedores, a especificação ECMAScript 2015 introduziu dois novos tipos de objetos iteráveis: Maps, que são coleções ordenadas de pares chave-valor e Conjuntos, que são coleções de valores únicos.

      Neste artigo, você irá analisar os objetos Map e Conjunto, o que os torna semelhantes e diferentes dos Objetos e Matrizes, as propriedades e métodos disponíveis para eles, bem como exemplos de alguns usos práticos.

      Maps

      Um Map é uma coleção de pares chave-valor que pode usar qualquer tipo de dados como uma chave e manter a ordem de suas entradas. Os Maps têm elementos de ambos os Objetos (uma coleção única de pares chave-valor) e Matrizes (uma coleção ordenada). Porém, conceitualmente, eles são mais parecidos aos Objetos. Isso acontece porque, embora o tamanho e a ordem das entradas sejam preservados como em uma Matriz, as entradas – propriamente ditas – são pares chave-valor, como os Objetos.

      Os Maps podem ser inicializados com a sintaxe new Map():

      const map = new Map()
      

      Isso nos dá um Map vazio:

      Output

      Map(0) {}

      Como adicionar valores a um Map

      Você pode adicionar valores a um mapa com o método set(). O primeiro argumento será a chave e o segundo argumento será o valor.

      Isto adiciona três pares chave-valor ao map:

      map.set('firstName', 'Luke')
      map.set('lastName', 'Skywalker')
      map.set('occupation', 'Jedi Knight')
      

      Aqui, começamos a ver como os Maps têm elementos tanto de Objetos como de Matrizes. Assim como acontece com uma Matriz, temos uma coleção com índice zero e podermos ver também quantos itens estão no Map por padrão. Os Maps usam a sintaxe => para representar os pares chave-valor como key => value:

      Output

      Map(3) 0: {"firstName" => "Luke"} 1: {"lastName" => "Skywalker"} 2: {"occupation" => "Jedi Knight"}

      Esse exemplo se assemelha a um objeto regular com chaves baseadas em string, mas podemos usar qualquer tipo de dados como uma chave com os Maps.

      Além de definir manualmente os valores em um Map, podemos também inicializar um Map já com valores. Fazemos isso usando uma Matriz de Matrizes contendo dois elementos, sendo cada um um par chave-valor, que têm a seguinte aparência:

      [ [ 'key1', 'value1'], ['key2', 'value2'] ]
      

      Ao usar a sintaxe a seguir, podemos recriar o mesmo Map:

      const map = new Map([
        ['firstName', 'Luke'],
        ['lastName', 'Skywalker'],
        ['occupation', 'Jedi Knight'],
      ])
      

      Nota: este exemplo usa as vírgulas à direita, também conhecidas como vírgulas pendentes. Trata-se de uma prática de formatação do JavaScript na qual o item final de uma série – ao se declarar uma coleção de dados – tem uma vírgula no final. Embora essa escolha de formatação possa ser usada para obter diferenças de limpeza e uma manipulação de código mais fácil, usar isso ou não é uma questão de preferência. Para obter mais informações sobre as vírgulas à direita, consulte este artigo de Vírgulas à direita dos documentos Web da MDN (Mozilla Developer Network).

      A propósito, essa sintaxe é a mesma do resultado da chamada Object.entries() em um Objeto. Isso proporciona uma maneira pronta de converter um Objeto em um Map, como mostrado no bloco de código a seguir:

      const luke = {
        firstName: 'Luke',
        lastName: 'Skywalker',
        occupation: 'Jedi Knight',
      }
      
      const map = new Map(Object.entries(luke))
      

      Como alternativa, você pode transformar um Map de volta em um Objeto ou uma Matriz com uma única linha de código.

      O seguinte converte um Map em um Objeto:

      const obj = Object.fromEntries(map)
      

      Isso resultará no seguinte valor de obj:

      Output

      {firstName: "Luke", lastName: "Skywalker", occupation: "Jedi Knight"}

      Agora, vamos converter um Map em uma Matriz:

      const arr = Array.from(map)
      

      Isso resultará na seguinte Matriz para arr:

      Output

      [ ['firstName', 'Luke'], ['lastName', 'Skywalker'], ['occupation', 'Jedi Knight'] ]

      Chaves de Map

      Os Maps aceitam qualquer tipo de dados como uma chave e não permitem valores de chave duplicados. Podemos demonstrar isso criando um mapa e usando valores não string como chaves, além de definir dois valores para a mesma chave.

      Primeiro, vamos inicializar um mapa com chaves não string:

      const map = new Map()
      
      map.set('1', 'String one')
      map.set(1, 'This will be overwritten')
      map.set(1, 'Number one')
      map.set(true, 'A Boolean')
      

      Esse exemplo irá sobrepor a primeira chave de 1 com a seguinte e tratará a string '1' e o número 1 como chaves únicas:

      Output

      0: {"1" => "String one"} 1: {1 => "Number one"} 2: {true => "A Boolean"}

      Embora acredite-se que um Objeto regular JavaScript já possa lidar com os Números, os booleanos e outros tipos de dados primitivos como chaves, isso não é, de fato, o caso, já que Objetos transformam todas as chaves em strings.

      Como exemplo, inicialize um objeto com uma chave numérica e compare o valor para a chave numérica 1 e a chave em string "1":

      // Initialize an object with a numerical key
      const obj = { 1: 'One' }
      
      // The key is actually a string
      obj[1] === obj['1']  // true
      

      É por isso que, se você tentar usar um Objeto como uma chave, ele imprimirá a string object Object em vez disso.

      Como exemplo, crie um Objeto e, em seguida, use-o como chave de outro Objeto:

      // Create an object
      const objAsKey = { foo: 'bar' }
      
      // Use this object as the key of another object
      const obj = {
        [objAsKey]: 'What will happen?'
      }
      

      Isso irá resultar no seguinte:

      Output

      {[object Object]: "What will happen?"}

      Isso não acontece com o Map. Tente criar um Objeto e configurá-lo como a chave de um Map:

      // Create an object
      const objAsKey = { foo: 'bar' }
      
      const map = new Map()
      
      // Set this object as the key of a Map
      map.set(objAsKey, 'What will happen?')
      

      Agora, a key do elemento Map é o objeto que criamos.

      Output

      key: {foo: "bar"} value: "What will happen?"

      Existe uma coisa importante a se observar sobre o uso de um Objeto ou Matriz como uma chave: o Map está usando a referência ao Objeto para comparar a igualdade, não o valor literal do Objeto. No JavaScript {} === {} retorna false, uma vez que os dois Objetos não são os mesmos dois Objetos, apesar de terem o mesmo valor (vazio).

      Isso significa que adicionar dois Objetos únicos com o mesmo valor criará um Map com duas entradas:

      // Add two unique but similar objects as keys to a Map
      map.set({}, 'One')
      map.set({}, 'Two')
      

      Isso irá resultar no seguinte:

      Output

      Map(2) {{…} => "One", {…} => "Two"}

      No entanto, usar a mesma referência de Objeto duas vezes criará um Map com uma entrada.

      // Add the same exact object twice as keys to a Map
      const obj = {}
      
      map.set(obj, 'One')
      map.set(obj, 'Two')
      

      O que dará como resultado o seguinte:

      Output

      Map(1) {{…} => "Two"}

      O segundo set() está atualizando exatamente a mesma chave que a primeira, de modo que acabamos com um Map que possui apenas um valor.

      Obtendo e excluindo itens de um Map

      Uma das desvantagens de se trabalhar com Objetos é que pode ser difícil enumerá-los, ou trabalhar com todos as chaves ou valores. A estrutura do Map, ao contrário, possui muitas propriedades embutidas que tornam mais direto o trabalho com seus elementos.

      Podemos inicializar um novo Map para demonstrar os métodos e propriedades a seguir: delete(), has(), get() e size.

      // Initialize a new Map
      const map = new Map([
        ['animal', 'otter'],
        ['shape', 'triangle'],
        ['city', 'New York'],
        ['country', 'Bulgaria'],
      ])
      

      Use o método has() para verificar se existe um item em um mapa. O has() retornará um Booleano.

      // Check if a key exists in a Map
      map.has('shark') // false
      map.has('country') // true
      

      Use o método get() para recuperar um valor pela chave.

      // Get an item from a Map
      map.get('animal') // "otter"
      

      Um benefício em particular que os Maps têm em relação aos Objetos é que você pode descobrir o tamanho de um Map a qualquer momento, assim como com uma Matriz. É possível obter a contagem de itens em um Map com a propriedade size (tamanho). Isso envolve menos passos do que converter um Objeto em uma Matriz para descobrir seu tamanho.

      // Get the count of items in a Map
      map.size // 4
      

      Use o método delete() para remover um item de um Map pela chave. O método retornará um Booleano — true se já houver um item e tiver sido excluído e retornará um false se não corresponder a nenhum item.

      // Delete an item from a Map by key
      map.delete('city') // true
      

      Isso resulta no seguinte Map:

      Output

      Map(3) {"animal" => "otter", "shape" => "triangle", "country" => "Bulgaria"}

      Por fim, é possível limpar todos os valores do Map com o método map.clear().

      // Empty a Map
      map.clear()
      

      Isso produzirá o seguinte resultado:

      Output

      Map(0) {}

      Chaves, valores e entradas para Maps

      Os Objetos podem recuperar chaves, valores e entradas, usando as propriedades do construtor Object. Os Maps, por outro lado, têm métodos protótipos que nos permitem obter diretamente as chaves, valores e entradas da instância Map.

      Os métodos keys(), values() e entries() retornam todos um MapIterator, que se assemelha a uma Matriz na qual você pode usar for...of executar o loop nos valores.

      Apresentamos a seguir outro exemplo de um Map, que podemos usar para demonstrar esses métodos:

      const map = new Map([
        [1970, 'bell bottoms'],
        [1980, 'leg warmers'],
        [1990, 'flannel'],
      ])
      

      O método keys() retorna as chaves:

      map.keys()
      

      Output

      MapIterator {1970, 1980, 1990}

      O método values() retorna os valores:

      map.values()
      

      Output

      MapIterator {"bell bottoms", "leg warmers", "flannel"}

      O método entries() retorna uma matriz de pares chave-valor:

      map.entries()
      

      Output

      MapIterator {1970 => "bell bottoms", 1980 => "leg warmers", 1990 => "flannel"}

      Iteração com Map

      O Map tem um método integrado forEach, similar a uma Matriz, para iteração integrada. No entanto, existe um pouco de diferença quanto ao que eles iteram. O callback (retorno de chamada) do forEach de um Map itera value, key e map, propriamente dito, ao passo que a versão Matriz itera item, index e array, propriamente dito.

      // Map
      Map.prototype.forEach((value, key, map) = () => {})
      
      // Array
      Array.prototype.forEach((item, index, array) = () => {})
      

      Trata-se de uma grande vantagem dos Maps em relação aos Objetos, uma vez que os Objetos precisam ser convertidos com keys(), values(), ou entries() e não há uma maneira simples de recuperar as propriedades de um Objeto sem convertê-lo.

      Para demonstrar isso, vamos iterar nosso Map e registrar os pares chave-valor no console:

      // Log the keys and values of the Map with forEach
      map.forEach((value, key) => {
        console.log(`${key}: ${value}`)
      })
      

      Isso dará:

      Output

      1970: bell bottoms 1980: leg warmers 1990: flannel

      Como um loop for...of itera items iteráveis como Maps e Matrizes, podemos obter exatamente o mesmo resultado por meio da desestruturação da matriz dos itens do Map:

      // Destructure the key and value out of the Map item
      for (const [key, value] of map) {
        // Log the keys and values of the Map with for...of
        console.log(`${key}: ${value}`)
      }
      

      Propriedades e métodos de Map

      A tabela a seguir mostra uma lista de propriedades e métodos de Map, para referência rápida:

      Propriedades/Métodos Descrição Retorna
      set(key, value) Adiciona um par chave-valor a um Map Objeto Map
      delete(key) Remove um par chave-valor de um Map por chave Booleano
      get(key) Retorna um valor por meio da chave valor
      has(key) Verifica quanto à presença de um elemento em um Map por chave Booleano
      clear() Remove todos os itens de um Map N/A
      keys() Retorna todas as chaves em um Map Objeto MapIterator
      values() Retorna todas os valores em um Map Objeto MapIterator
      entries() Retorna todas as chaves e valores em um Map como [key, value] Objeto MapIterator
      forEach() Itera no Map por ordem de inserção N/A
      size Retorna o número de itens em um Map Número

      Quando usar um Map

      Em suma, os Maps são semelhantes aos Objetos no sentido de que têm pares de chave-valor, mas os Maps têm diversas vantagens em relação aos objetos:

      • Tamanho – Os Maps têm uma propriedade size, ao passo que os Objetos não têm uma maneira integrada de descobrir seu tamanho.
      • Iteração – Os Maps podem ser iterados diretamente, ao passo que os Objetos não.
      • Flexibilidade – Os Maps podem ter qualquer tipo de dados (primitivo ou Objeto) como a chave para um valor, enquanto Objetos admitem apenas strings.
      • Ordenados – Os Maps retêm sua ordem de inserção, ao passo que os objetos não têm uma ordem garantida.

      Devido a esses fatores, os Maps são uma estrutura de dados avançada a se considerar. No entanto, os Objetos têm também algumas vantagens importantes:

      • JSON – Os Objetos funcionam de maneira impecável com JSON.parse() e JSON.stringify(), duas funções essenciais para se trabalhar com o JSON, um formato de dados comum com os quais muitas APIs REST lidam.
      • Trabalhar com um único elemento – Ao trabalhar com um valor conhecido em um Objeto, você pode acessá-lo diretamente com a chave, sem a necessidade de usar um método, como o get() do Map.

      Essa lista ajudará você a decidir se um Map ou um Objeto é a estrutura de dados correta para o seu caso de uso.

      Conjunto

      Um Conjunto é uma coleção de valores únicos. Ao contrário de um Map, um Conjunto é conceitualmente mais parecido com uma Matriz do que um com um Objeto, já que é uma lista de valores e não pares chave-valor. No entanto, o Conjunto não é um substituto da Matriz, mas sim um suplemento que provém suporte adicional para se trabalhar com dados duplicados.

      Você pode inicializar os Conjuntos com a sintaxe new Set().

      const set = new Set()
      

      Isso nos dá um Conjunto vazio:

      Output

      Set(0) {}

      Os itens podem ser adicionados a um Conjunto com o método add(). (Isso não deve ser confundido com o método set() disponível para Map, embora sejam semelhantes.)

      // Add items to a Set
      set.add('Beethoven')
      set.add('Mozart')
      set.add('Chopin')
      

      Como os Conjuntos podem conter apenas valores únicos, qualquer tentativa de adicionar um valor que já exista será ignorada.

      set.add('Chopin') // Set will still contain 3 unique values
      

      Nota: a mesma comparação de igualdade que se aplica às chaves do Map se aplica aos itens do Conjunto. Dois objetos que têm o mesmo valor, mas não compartilham a mesma referência não serão considerados iguais.

      Também é possível inicializar os Conjuntos com uma Matriz de valores. Se houver valores duplicados na matriz, eles serão removidos do Conjunto.

      // Initialize a Set from an Array
      const set = new Set(['Beethoven', 'Mozart', 'Chopin', 'Chopin'])
      

      Output

      Set(3) {"Beethoven", "Mozart", "Chopin"}

      Por outro lado, um Conjunto pode ser convertido em uma Matriz com apenas uma linha de código:

      const arr = [...set]
      

      Output

      (3) ["Beethoven", "Mozart", "Chopin"]

      O Conjunto possui muitos dos mesmos métodos e propriedades do Mapa, incluindo delete(), has(), clear() e size.

      // Delete an item
      set.delete('Beethoven') // true
      
      // Check for the existence of an item
      set.has('Beethoven') // false
      
      // Clear a Set
      set.clear()
      
      // Check the size of a Set
      set.size // 0
      

      Observe que o Conjunto não tem um modo de acessar um valor por uma chave ou índice, como Map.get(key) ou arr[index].

      Chaves, valores e entradas para Conjuntos

      Tanto o Map quanto o Conjunto possui os métodos keys(), values() e entries() que retornam um Iterator. No entanto, embora cada um desses métodos tenha um objetivo distinto no Map, os Conjuntos não têm chaves e, portanto, chaves são um alias para os valores. Isso significa que os métodos keys() e values() retornarão o mesmo Iterator e as entries() retornarão o valor duas vezes. Assim, faz todo sentido usar apenas values() com Conjuntos, já que existem outros dois métodos para obter consistência e compatibilidade cruzada com o Map.

      const set = new Set([1, 2, 3])
      // Get the values of a set
      set.values()
      

      Output

      SetIterator {1, 2, 3}

      Iteração com Conjunto

      Assim como o Map, o Conjunto possui o método embutido forEach(). Como os Conjuntos não têm chaves, o primeiro e segundo parâmetros do callback do forEach() retornam o mesmo valor, de modo que não existe um caso de uso para ele além da compatibilidade com o Map. Os parâmetros do forEach() são (value, key, set).

      Tanto forEach() quanto for...of podem ser usado no Conjunto. Primeiro, vamos examinar a iteração forEach():

      const set = new Set(['hi', 'hello', 'good day'])
      
      // Iterate a Set with forEach
      set.forEach((value) => console.log(value))
      

      Depois, podemos escrever a versão for...of:

      // Iterate a Set with for...of
      for (const value of set) {  
          console.log(value);
      }
      

      Ambas essas estratégias resultarão no seguinte:

      Output

      hi hello good day

      Propriedades e métodos do Conjunto

      A tabela a seguir mostra uma lista de propriedades e métodos do Conjunto para referência rápida:

      Propriedades/Métodos Descrição Retorna
      add(value) Adiciona um novo item em um Conjunto Objeto Set
      delete(value) Remove o item especificado de um Conjunto Booleano
      has() Verifica quanto à presença de um item em um Conjunto Booleano
      clear() Remove todos os itens de um Conjunto N/A
      keys() Retorna todos os valores de um Conjunto (o mesmo que values()) Objeto SetIterator
      values() Retorna todos os valores de um Conjunto (o mesmo que keys()) Objeto SetIterator
      entries() Retorna todos os valores de um Conjunto como [value, value] Objeto SetIterator
      forEach() Itera no Conjunto por ordem de inserção N/A
      size Retorna o número de itens em um Conjunto Número

      Quando usar um Conjunto

      O Conjunto é um complemento útil ao seu conjunto de ferramentas do JavaScript, especialmente para trabalhar com valores duplicados de dados.

      Numa única linha, podemos criar uma nova Matriz, sem duplicar valores de uma Matriz que possua valores duplicados.

      const uniqueArray = [ ...new Set([1, 1, 2, 2, 2, 3])] // (3) [1, 2, 3]
      

      Isso dará:

      Output

      (3) [1, 2, 3]

      O Conjunto pode ser usado para encontrar a união, a intersecção e a diferença entre dois conjuntos de dados. No entanto, as Matrizes têm uma vantagem significativa em relação aos Conjuntos para manipulação adicional dos dados, devidos aos métodos sort(), map(), filter() e reduce(), bem como uma compatibilidade direta com os métodos JSON.

      Conclusão

      Neste artigo, você aprendeu que um Map é uma coleção de pares chave-valor ordenados e que um Conjunto é uma coleção de valores únicos. Ambas essas estruturas de dados contribuem com capacidades adicionais ao JavaScript e simplificam tarefas comuns, como descobrir o tamanho de uma coleção de pares chave-valor e remover itens duplicados de um conjunto de dados, respectivamente. Por outro lado, Objetos e Matrizes vem sendo tradicionalmente usados para o armazenamento e manipulação de dados no JavaScript. Eles têm compatibilidade direta com o JSON, fazendo deles as estruturas de dados mais essenciais, especialmente para trabalhar com as APIs REST. Os Maps e Conjuntos são úteis principalmente como estruturas de dados que auxiliam os Objetos e as Matrizes.

      Se quiser aprender mais sobre o JavaScript, confira a página inicial de nossa série sobre Como programar em JavaScript, ou pesquise nossa série sobre Como programar em Node.js para obter artigos sobre o desenvolvimento de back-end.



      Source link