Notes Javascript - Keyed Collections



Keyed Collections

Keyed collections differ from Arrays in how they index information. An array uses integers to reference an item. A keyed collection uses a key, which can take many forms. Keyed collections in Javascript include the Map Object and the Set Object.


Map Object

A Map object is a simple key/value map and can iterate its elements in insertion order.

const sayings = new Map(); sayings.set("dog", "woof"); sayings.set("cat", "meow"); sayings.set("elephant", "toot"); sayings.size; // 3 sayings.get("dog"); // woof sayings.get("fox"); // undefined sayings.has("bird"); // false sayings.delete("dog"); sayings.has("dog"); // false for (const [key, value] of sayings) { console.log(`${key} goes ${value}`); } // "cat goes meow" // "elephant goes toot" sayings.clear(); sayings.size; // 0

Object And Map Compared

Traditionally, objects have been used to map strings to values. Objects allow you to set keys to values, retrieve those values, delete keys, and detect whether something is stored at a key. Map objects, however, have a few more advantages that make them better maps.

These three tips can help you to decide whether to use a Map or an Object:

WeakMap Object

There is another Map-like object called a WeakMap Object. The following is a brief description of what a WeakMap is. There won't be any discussion of it beyond the description.

A WeakMap is a collection of key/value pairs whose keys must be objects or non-registered symbols, with values of any arbitrary JavaScript type, and which does not create strong references to its keys. That is, an object's presence as a key in a WeakMap does not prevent the object from being garbage collected. Once an object used as a key has been collected, its corresponding values in any WeakMap become candidates for garbage collection as well, as long as they aren't strongly referred to elsewhere. The only primitive type that can be used as a WeakMap key is symbol, more specifically, non-registered symbols, because non-registered symbols are guaranteed to be unique and cannot be re-created.

The WeakMap API is essentially the same as the Map API. However, a WeakMap doesn't allow observing the liveness of its keys, which is why it doesn't allow enumeration. So there is no method to obtain a list of the keys in a WeakMap. If there were, the list would depend on the state of garbage collection, introducing non-determinism.

One use case of WeakMap objects is to store private data for an object, or to hide implementation details.


Set Object

Set objects are collections of unique values. You can iterate its elements in insertion order. A value in a Set may only occur once; it is unique in the Set's collection.

The following code shows some basic operations with a Set.

const mySet = new Set(); mySet.add(1); mySet.add("some text"); mySet.add("foo"); mySet.has(1); // true mySet.delete("foo"); mySet.size; // 2 for (const item of mySet) { console.log(item); } // 1 // "some text"


Array And Set Compared

Traditionally, a set of elements has been stored in arrays, the Set object, however, has some advantages:


Converting Between Array And Set

You can create an Array from a Set using Array.from or the spread syntax. Also, the Set constructor accepts an Array to convert in the other direction.

Set objects store unique values—so any duplicate elements from an Array are deleted when converting from Array to Set!

const myArr = ["Some text 1","Some text 2","Some text 3"] const mySet = new Set(); mySet.add("Some text 1"); mySet.add("Some text 2"); mySet.add("Some text 3"); // SET TO ARRAY var myAr1 = Array.from(mySet); var myAr2 = [...mySet]; // ARRAY TO SET mySet2 = new Set([1, 2, 3, 4]); mySet3 = new Set(myArr);

function runScript1() { let divResult = document.getElementById("results1"); let myArr = ["Array text 1","Array text 2","Array text 3"] let mySet = new Set(); mySet.add("Set text 1"); mySet.add("Set text 2"); mySet.add("Set text 3"); // CREATE AN ARRAY FROM mySet USING Array.from() let myArr2 = Array.from(mySet); // CREATE AN ARRAY FROM mySet USING SPREAD NOTATION let myArr3 = [...mySet]; // CREATE A SET FROM AN ARRAY let mySet2 = new Set(myArr); // SHOW CONTENTS OF ARRAY 1 divResult.innerHTML = "Array 1:<br/>"; for (var i = 0; i < myArr2.length; i++) { divResult.innerHTML += myArr2[i] + "<br/>"; } // SHOW CONTENTS OF ARRAY 2 divResult.innerHTML += "Array 2:<br/>"; for (var i = 0; i < myArr3.length; i++) { divResult.innerHTML += myArr3[i] + "<br/>"; } // SHOW CONTENTS OF SET 1 divResult.innerHTML += "Set 1:<br/>"; for (const item of mySet2) { divResult.innerHTML += item + "<br/>"; } }

Run Test Script