JavaScript/Objekte/Map/set
Die Methode set
dient dazu, einer Map Einträge hinzuzufügen oder bestehende Einträge zu überschreiben.
Syntax
set(key, value);
- Parameter
-
key
- Der Schlüssel für den Eintrag, der geschrieben werden soll.
value
- Der zu speichernde Wert
Beide Parameter sind optional. Werden sie weggelassen, verwendet die set
-Methode den Wert undefined
.
- Rückgabewert
- Das
Map
-Objekt, auf demset
aufgerufen wurde.
Beschreibung
Nachdem eine Map erzeugt wurde, können weitere Einträge nur noch einzeln hinzugefügt werden. Für diesen Zweck gibt es die Methode set. Sie prüft zunächst, ob es den angegebenen Schlüssel bereits in der Map gibt. Wenn ja, wird sein Wert überschrieben. Wenn nicht, wird der Map ein neuer Schlüssel hinzugefügt und der Wert darunter gespeichert.
const map = new Map( );
map.set('self', 'html');
map.set('wiki', 'text');
map.set('forum', 'dialog');
map.set('self', 'die energie des verstehens');
console.log(map.has('self')); // true
console.log(Array.from(map.keys())); // ['self', 'wiki', 'forum']
In diesem Beispiel wird eine leere Map erzeugt, auf der danach viermal die Methode set aufgerufen wird, wobei jeweils ein String für Schlüssel und Wert als Argument übergeben wird. Der Schlüssel 'self' wird zweimal geschrieben, so dass 'html' durch 'die energie des verstehens' ersetzt wird.
Schließlich wird mit der Methode has überprüft, ob der Eintrag 'self' auch wirklich hinzugefügt wurde und das Ergebnis dieses Methodenaufrufs in die Konsole geschrieben.
Um das zu zeigen, ruft das Beispiel zum Abschluss die Schlüsselliste ab und gibt sie ebenfalls aus. Der Schlüssel 'self'
ist vorne geblieben. Allerdings liefert die keys
-Methode kein Array, sondern einen sogenannten Iterator für die gespeicherten Schlüssel, der von console.log
nicht aufgelistet wird. Array.from
durchläuft den Iterator und erstellt ein Array aus den Schlüsseln.
Verkettung von Aufrufen
Da der Rückgabewert der Methode set immer eine Referenz auf die Map ist, auf der die Methode aufgerufen wurde, ist es möglich mehrere Aufruf hintereinander auszuführen, ohne die jeweilige Map erneut referenzieren zu müssen. Die Aufrufe der Methode set können also verkettet werden.
const map = new Map( ).set('self', 'html').set('wiki', 'text').set('forum', 'dialog').set('self', 'energie');
console.log(Array.from(map.keys())); // ['self', 'wiki', 'forum']
Wie vorhin wird eine leere Map erzeugt, aber die set-Aufrufe erfolgen nicht einzeln auf dem Objekt, das in der Variablen map
steht, sondern werden direkt auf dem jeweils zurückgegebenen Map
-Objekt des vorhigen Aufrufs durchgeführt. Erst am Ende wird der letzte Rückgabewert in der Variablen gespeichert.
Die Liste der erzeugten Schlüssel wird im Anschluss ausgegeben.
Die verkettete Schreibweise spart zwar Quellcode, hat aber keine Vorteile bei der Ausführungsgeschwindigkeit. Falls Sie eine Funktion erstellen, die eine Map erzeugt und mit Werten initialisiert, dann können Sie - wenn die Programmlogik das zulässt - eine solche Aufruffolge direkt hinter die return
Anweisung schreiben und sich damit eine Variable sparen. Besonders lesbar ist das allerdings nicht, Sie sollten ein solches Konstrukt möglichst auf mehrere Zeilen verteilen:
const map = new Map( )
.set('self', 'html')
.set('wiki', 'text')
.set('forum', 'dialog');
console.log(Array.from(map.keys())); // ['self', 'wiki', 'forum']
TypeError: Map.set is not a constructor
:
const map = new Map.set('key', 'value');
Der Punkt-Operator („Methodenzugriffsoperator“) ist höher priorisiert ist als der new
-Operator, deshalb wird zuerst Map.set
ermittelt und erst darauf new
anwendet. Map.set
ist aber keine Konstruktorfunktion, sondern hat den Wert undefined
(set
ist eine Eigenschaft von Map.prototype
).
Entweder fügen Sie hinter Map ein leeres Klammerpaar an, so wie es hier alle Beispiele tun, oder sie setzen new Map
in Klammern:
const map1 = new Map().set('self', 'html'); // leere Argumentklammern - funktioniert
const map2 = (new Map).set('self', 'html'); // gibt new Vorrang vor . - funktioniert
Datentypen für Map-Einträge
Im Gegensatz zu anderen assoziativen Speichern ist ein Map-Objekt nicht auf Zeichenketten als Schlüssel angewiesen. Jeder JavaScript-Typ ist zulässig, sogar Objekte.
const map = new Map();
const keyObject = { name: "foo" };
map.set("42", "vier-zwei");
map.set(42, "zweiundvierzig")
map.set(keyObject, "bar");
map.set({ name: "self"}, "html");
console.log(map.get("42"), map.get(42), map.get(keyObject), map.get({ name: "self"}));
// vier-zwei zweiundvierzig bar undefined
// ^----- Nanu?
Die Zeichenkette '42' und die Zahl 42, die vom ==
-Operator als gleich registriert würden, haben unterschiedliche Typen und bilden deshalb unterschiedliche Schlüssel.
Dass der Zugriff auf { name: "self"; }
das Ergebnis undefined
hat, mag Sie vielleicht überraschen. Es hat doch mit keyObject
gut funktioniert, warum nicht mit dem Objektliteral? JavaScript erzeugt für jede Verwendung eines Objektliterals ein neues Objekt, so dass hier der Schlüssel, unter dem "html" geschrieben wurde, nicht identisch ist mit dem, der nachher zum Lesen verwendet wird.
Weblinks
- ECMAScript Spezifikation: Map.prototype.set
- MDN: Map.prototype.set