- read

Keyed Collections: Set, Weak Set, Map and Weak Map in JavaScript

The Software Line 29

Keyed Collections: Set, Weak Set, Map and Weak Map in JavaScript

It’s fundamental to have the knowledge about these data types — you don’t need to use objects and arrays for everything

The Software Line
Level Up Coding
Published in
5 min read5 hours ago

--

Photo by Ryland Dean on Unsplash

Like in every other programming language, be proficient with data structures, it’s crucial for everyday work.

In JavaScript, developers are using often Object and Array data structures for everything, but only because they never check for the other options. JavaScript keyed collections are structured collections of data that store values and provide methods for easily accessing them. Sounds a lot like arrays and objects, right?

So, let’s start with the keyed collections:

1. Set

To keep it simple — it’s a collection of the unique values (numbers, strings, …) without duplicates. When you add new elements to the set, you can chain add method because the updated set object is returned after every call. We have several methods available, so we can check if specific element is available inside the set, delete specific element from the set or delete all elements from the set. It’s not possible to truncate the Set, so the update for the size property will be ignored. Also, it’s possible to loop through the set with for-of loop or use for each, values or keys methods from the Set.

const data = new Set(); // empty set created

data.add('foo').add('bar').add('baz').add('baz');
printSetData(data);

console.log(data.has('foo'));

data.delete('baz');
printSetData(data);

data.clear();
printSetData(data);

data.add('Bar').add('Baz');
printSetData(data);

data.size = 1; // nothing happens
printSetData(data);

for (const item of data) {
console.log('set item: ', item)
}

function printSetData(data) {
console.log(data, data.size);
}

// Set { 'foo', 'bar', 'baz' } 3
// true
// Set { 'foo', 'bar' } 2
// Set {} 0
// Set { 'Bar', 'Baz' } 2
// Set { 'Bar', 'Baz' } 2
// set item: Bar
// set item: Baz

2. WeakSet

Weak Set is a very similar data structure to Set but with some very important differences:

  • we can only add objects to Weak Set collection
  • an object exists in the set while it is reachable from somewhere else
  • Like Set, Weak Set supports add, has and delete methods but size, keys and other methods are not supported, as well as the iterations

So, the biggest problem with Weak Set is not having the iterations and the ability to show the whole content of the Weak Set. Once again, only add, has and delete methods are available, nothing else. It’s not possible to check the size of the Weak Set.

const weakSet = new WeakSet(); // empty WeakSet created
let foo = { name: 'foo' };
let bar = { name: 'bar' };
let baz = { name: 'baz' };

weakSet.add(foo).add(bar).add(baz).add(baz);

checkWeakSet(weakSet, foo, bar, baz);

bar = baz = null; // bar and baz are not available in WeakSet anymore

checkWeakSet(weakSet, foo, bar, baz)

console.log(weakSet); // WeakSet { <items unknown> }

function checkWeakSet(setData, ...items) {
for (const item of items) {
console.log("item available in weakSet: ", setData.has(item), item)
}
}

// item available in weakSet: true { name: 'foo' }
// item available in weakSet: true { name: 'bar' }
// item available in weakSet: true { name: 'baz' }
// item available in weakSet: true { name: 'foo' }
// item available in weakSet: false null
// item available in weakSet: false null

3. Map

Basically, a Map is the collection of key and value pairs, where the insertion order of the pairs is respected. Any value can represent the key inside the map (both objects and primitive values such as string, number, boolean and others). Also, it is possible to iterate through the map with for-of loop or with some of the methods such as keys, values, for each or entries.

const map = new Map(); // empty map created
map.set('key1', 'foo').set('key2', 'bar').set('key3', 'baz');

console.log(map.has('key1'));

map.delete('key3');
printMapData(map);

map.clear();
printMapData(map);

const baz = { name: 'baz' };
map.set('key1', 'foo').set('key2', 'bar').set(baz, 'baz');
printMapData(map);

console.log(map.has(baz));

for (const [key, value] of map) {
console.log(`key = ${key} and value = ${value}`);
}

function printMapData(data) {
console.log(data, data.size);
}

// true
// Map { 'key1' => 'foo', 'key2' => 'bar' } 2
// Map {} 0
// Map { 'key1' => 'foo', 'key2' => 'bar', { name: 'baz' } => 'baz' } 3
// true
// key = key1 and value = foo
// key = key2 and value = bar
// key = [object Object] and value = baz

4. WeakMap

WeakMap must contain only objects as keys. Then, if the object used as key inside the Weak Map is no longer available, it will be automatically removed from the Weak Map. Unlike Map, here we have only four methods available — get, set, delete and has. Like with Weak Set, it’s not possible to iterate through the Weak Map and show the whole state of the Weak Map data. Also, it’s not possible to check the size of the Weak Map.

const weakMap = new WeakMap();
let foo = { name: 'foo' };
let bar = { name: 'bar' };
let baz = { name: 'baz' };

weakMap.set(foo, 'foo').set(bar, 'bar').set(baz, 'baz');

console.log(weakMap.has(foo));
console.log(weakMap.get(bar));

weakMap.delete(baz);

checkWeakMap(weakMap, foo, bar, baz);

bar = null; // bar is not available in WeakMap anymore

checkWeakMap(weakMap, foo, bar, baz);

console.log(weakMap); // WeakMap { <items unknown> }

function checkWeakMap(mapData, ...items) {
for (const item of items) {
console.log("item available in weakMap: ", mapData.has(item), item)
}
}

// true
// bar

// item available in weakMap: true { name: 'foo' }
// item available in weakMap: true { name: 'bar' }
// item available in weakMap: false { name: 'baz' }

// item available in weakMap: true { name: 'foo' }
// item available in weakMap: false null
// item available in weakMap: false { name: 'baz' }

// WeakMap { <items unknown> }

Conclusion

We don’t need to have all data inside objects and arrays inside our Web applications. Beigng proficient with all data structures gives you real power when it comes to the handling of the Web application data flow. Always thinking about the performances in every context so always use sets to have unique values and maps when every value is related to specific key. If you want automatic updates for maps and sets and you need objects as keys then use weak map and weak set.

Thanks for reading.
I hope you enjoyed the article and learned something.