One place for hosting & domains

      Objects

      Copying Objects in JavaScript


      Objects are the fundamental blocks of JavaScript. An object is a collection of properties, and a property is an association between a key (or name) and a value. Almost all objects in JavaScript are instances of Object which sits on the top of the prototype chain.

      Introduction

      As you know, the assignment operator doesn’t create a copy of an object, it only assigns a reference to it, let’s look at the following code:

      let obj = {
        a: 1,
        b: 2,
      };
      let copy = obj;
      
      obj.a = 5;
      console.log(copy.a);
      // Result 
      // a = 5;
      

      The obj variable is a container for the new object initialized. The copy variable is pointing to the same object and is a reference to that object. So basically this { a: 1, b: 2, } object is saying: There are now two ways to gain access to me. You have to pass through the obj variable or the copy variable either ways you still get to me and anything you do to me via these ways (gateways) will affect me.

      Immutability is widely spoken about these days and you have to listen to this call! This method removes any form of immutability and could lead to bugs should the original object be used by another part of your code.

      The Naive Way of Copying Objects

      The naive way of copying objects is looping through the original object and copying each property one after the other. Let’s take a look at this code:

      function copy(mainObj) {
        let objCopy = {}; // objCopy will store a copy of the mainObj
        let key;
      
        for (key in mainObj) {
          objCopy[key] = mainObj[key]; // copies each property to the objCopy object
        }
        return objCopy;
      }
      
      const mainObj = {
        a: 2,
        b: 5,
        c: {
          x: 7,
          y: 4,
        },
      }
      
      console.log(copy(mainObj));
      
      

      Inherent Issues

      1. objCopy object has a new Object.prototype method different from the mainObj object prototype method, which is not what we want. We want an exact copy of the original object.
      2. Property descriptors are not copied. A “writable” descriptor with value set to be false will be true in the objCopy object.
      3. The code above only copies enumerable properties of mainObj.
      4. If one of the properties in the original object is an object itself, then it will be shared between the copy and the original making their respective properties point to the same object.

      Shallow Copying Objects

      An object is said to be shallow copied when the source top-level properties are copied without any reference and there exist a source property whose value is an object and is copied as a reference. If the source value is a reference to an object, it only copies that reference value to the target object.

      A shallow copy will duplicate the top-level properties, but the nested object is shared between the original(source) and the copy(target).

      Using Object.assign() method

      The Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object.

      let obj = {
        a: 1,
        b: 2,
      };
      let objCopy = Object.assign({}, obj);
      console.log(objCopy);
      // Result - { a: 1, b: 2 }
      

      Well, this does the job so far. We have made a copy of obj. Let’s see if immutability exist:

      let obj = {
        a: 1,
        b: 2,
      };
      let objCopy = Object.assign({}, obj);
      
      console.log(objCopy); // result - { a: 1, b: 2 }
      objCopy.b = 89;
      console.log(objCopy); // result - { a: 1, b: 89 }
      console.log(obj); // result - { a: 1, b: 2 }
      

      In the code above, we changed the value of the property 'b' in objCopy object to 89 and when we log the modified objCopy object in the console, the changes only apply to objCopy. The last line of code checks that the obj object is still intact and hasn’t change. This implies that we have successfully created a copy of the source object without any references to it.

      Pitfall of Object.assign()

      Not so fast! While we successfully created a copy and everything seem to be working fine, remember we discussed shallow copying? Let’s take a look at this example:

      let obj = {
        a: 1,
        b: {
          c: 2,
        },
      }
      let newObj = Object.assign({}, obj);
      console.log(newObj); // { a: 1, b: { c: 2} }
      
      obj.a = 10;
      console.log(obj); // { a: 10, b: { c: 2} }
      console.log(newObj); // { a: 1, b: { c: 2} }
      
      newObj.a = 20;
      console.log(obj); // { a: 10, b: { c: 2} }
      console.log(newObj); // { a: 20, b: { c: 2} }
      
      newObj.b.c = 30;
      console.log(obj); // { a: 10, b: { c: 30} }
      console.log(newObj); // { a: 20, b: { c: 30} }
      
      // Note: newObj.b.c = 30; Read why..
      
      

      Why is obj.b.c = 30?

      Well, that is a pitfall of Object.assign(). Object.assign only makes shallow copies. Both newObj.b and obj.b share the same reference to the object because of individual copies were not made, instead a reference to the object was copied. Any change made to any of the object’s property applies to all references using the object. How can we fix this? Continue reading… we have a fix in the next section.

      Note: Properties on the prototype chain and non-enumerable properties cannot be copied. See here:

      let someObj = {
        a: 2,
      }
      
      let obj = Object.create(someObj, { 
        b: {
          value: 2,  
        },
        c: {
          value: 3,
          enumerable: true,  
        },
      });
      
      let objCopy = Object.assign({}, obj);
      console.log(objCopy); // { c: 3 }
      
      
      • someObj is on obj’s prototype chain so it wouldn’t be copied.
      • property b is a non-enumerable property.
      • property c has an enumerable property descriptor allowing it to be enumerable. That’s why it was copied.

      Deep Copying Objects

      A deep copy will duplicate every object it encounters. The copy and the original object will not share anything, so it will be a copy of the original. Here’s the fix to the problem we encountered using Object.assign(). Let’s explore.

      Using JSON.parse(JSON.stringify(object));

      This fixes the issue we had earlier. Now newObj.b has a copy and not a reference! This is a way to deep copy objects. Here’s an example:

      let obj = { 
        a: 1,
        b: { 
          c: 2,
        },
      }
      
      let newObj = JSON.parse(JSON.stringify(obj));
      
      obj.b.c = 20;
      console.log(obj); // { a: 1, b: { c: 20 } }
      console.log(newObj); // { a: 1, b: { c: 2 } } (New Object Intact!)
      

      Immutable: ✓

      Pitfall

      Unfortunately, this method can’t be used to copy user-defined object methods. See below.

      Copying Object methods

      A method is a property of an object that is a function. In the examples so far, we haven’t copied an object with a method. Let’s try that now and use the methods we’ve learnt to make copies.

      let obj = {
        name: 'scotch.io',
        exec: function exec() {
          return true;
        },
      }
      
      let method1 = Object.assign({}, obj);
      let method2 = JSON.parse(JSON.stringify(obj));
      
      console.log(method1); //Object.assign({}, obj)
      /* result
      {
        exec: function exec() {
          return true;
        },
        name: "scotch.io"
      }
      */
      
      console.log(method2); // JSON.parse(JSON.stringify(obj))
      /* result
      {
        name: "scotch.io"
      }
      */
      
      

      The result shows that Object.assign() can be used to copy methods while JSON.parse(JSON.stringify(obj)) can’t be used.

      Copying Circular Objects

      Circular objects are objects that have properties referencing themselves. Let’s use the methods of copying objects we’ve learnt so far to make copies of a circular object and see if it works.

      Using JSON.parse(JSON.stringify(object))

      Let’s try JSON.parse(JSON.stringify(object)):

      // circular object
      let obj = { 
        a: 'a',
        b: { 
          c: 'c',
          d: 'd',
        },
      }
      
      obj.c = obj.b;
      obj.e = obj.a;
      obj.b.c = obj.c;
      obj.b.d = obj.b;
      obj.b.e = obj.b.c;
      
      let newObj = JSON.parse(JSON.stringify(obj));
      
      console.log(newObj); 
      

      Here’s the result:

      JSON.parse(JSON.stringify(obj)) clearly doesn’t work for circular objects.

      Using Object.assign()

      Let’s try Object.assign():

      // circular object
      let obj = { 
        a: 'a',
        b: { 
          c: 'c',
          d: 'd',
        },
      }
      
      obj.c = obj.b;
      obj.e = obj.a;
      obj.b.c = obj.c;
      obj.b.d = obj.b;
      obj.b.e = obj.b.c;
      
      let newObj2 = Object.assign({}, obj);
      
      console.log(newObj2); 
      

      Here’s the result:

      Object.assign() works fine for shallow copying circular objects but wouldn’t work for deep copying. Feel free to explore the circular object tree on your browser console. I’m sure you’ll find a lot of interesting work going on there.

      Using Spread Elements ( … )

      ES6 already has rest elements for array destructuring assignment and spread elements for array literals implemented. Take a look at spread element implementation on an array here:

      const array = [
        "a",
        "c",
        "d", {
          four: 4
        },
      ];
      const newArray = [...array];
      console.log(newArray);
      // Result 
      // ["a", "c", "d", { four: 4 }]
      
      

      The spread property for object literals is currently a Stage 3 proposal for ECMAScript. Spread properties in object initializers copies own enumerable properties from a source object onto the target object. The example below shows how easy it would be to copy an object once the proposal has been accepted.

      let obj = {
        one: 1,
        two: 2,
      }
      
      let newObj = { ...z };
      
      // { one: 1, two: 2 }
      

      Note: This will just be effective for shallow copy

      Conclusion

      Copying objects in JavaScript can be quite daunting especially if you’re new to JavaScript and don’t know your way around the language. Hopefully this article helped you understand and avoid future pitfalls you may encounter copying objects. If you have any library or piece of code that achieves a better result, feel welcome to share with the community. Happy coding!



      Source link

      How to Move Objects Between Buckets in Linode's Object Storage


      Updated by Linode

      Contributed by
      Linode

      Marquee image for How to Move Objects Between Buckets in Linode's Object Storage

      Note

      Linode’s Object Storage is a globally-available, S3-compatible method for storing and accessing data. With Object Storage more widely available, you may have buckets in multiple locations, this guide shows you how to move objects between buckets quickly and easily.

      In this guide you learn how to move objects between buckets using:

      Before You Begin

      To learn how to enable Object Storage, see the How to Use Object Storage guide.

      Object Storage is similar to a subscription service. After it is enabled, you are billed at the flat rate regardless of whether or not there are active buckets on your account. Cancel Object Storage to stop billing for this flat rate.

      In all Object Storage URLs the cluster where your bucket is hosted is a part of the URL string.

      Note

      A cluster is defined as all buckets hosted by a unique URL; for example: us-east-1.linodeobjects.com, ap-south-1.linodeobjects.com, or eu-central-1.linodeobjects.com.

      Cyberduck Graphical Interface

      The easiest way to move objects between buckets is using a Graphical User Interface (GUI) such as Cyberduck. Using a GUI, you can simply drag and drop objects between buckets.

      Transfer Between Buckets in the Same Cluster

      To transfer objects within the same cluster on the same account, you need to open only one Cyberduck window.

      1. Open Cyberduck and make a connection to access your buckets as described in How to Use Linode Object Storage.

      2. Expand the two buckets you want to transfer objects between by clicking the down arrow to the left of the folders.

      3. Locate the object you want to transfer.

      4. Drag the item from the source location to the destination.

        Drag a File to Move

      5. Select multiple items or folders and drag the group to the destination.

        Drag Multiple Files to Move

      Transfer Between Buckets in Different Clusters

      To transfer objects between two clusters, whether they are on the same account or not, you need to open two separate Cyberduck widows so that you can make two separate connections.

      Note

      Transferring objects between two different connections creates a copy of the object(s). If you don’t want the original files in the source bucket, you need to delete them after the transfer.

      1. Open Cyberduck, click the File menu and select New Browser. A second interface window appears where you can create another connection.

      2. In the first window, connect to the source bucket and locate the object you want to copy.

      3. In the second window, connect to the destination bucket and navigate to the location you want to place a copy of the object.

      4. Drag the object from the source to the destination.

        Select Objects to Move Between Cyberduck Windows

      Note

      You can easily copy multiple items, folders, or buckets by selecting everything you want to move and dragging the group. If you move a bucket to another bucket, it creates a folder with that bucket name.

      Cyberduck CLI

      You can also use the Cyberduck CLI, duck, to move objects from one bucket to another using the command line. The file transfer tool duck, is available for Linux, macOS, and Windows. To transfer using duck, you need the access keys that you generated for the source and destination buckets.

      1. Install duck using the instructions for your platform.

      2. Use the access keys and bucket names in the following command to move objects between buckets:

        duck --copy s3://[email protected]$bucket_source/source_object_file_name s3://[email protected]$bucket_destination/destination_object_file_name
        

        After issuing this command, you may be asked for login information.

      Note

      The bucket source and destination names are the fully qualified names including the cluster name, for example: us-east-1.linodeobjects.com/example_bucket.

      More Information

      You may wish to consult the following resources for additional information on this topic. While these are provided in the hope that they will be useful, please note that we cannot vouch for the accuracy or timeliness of externally hosted materials.

      This guide is published under a CC BY-ND 4.0 license.



      Source link

      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