DEV Community

colin-williams-dev
colin-williams-dev

Posted on • Updated on

Exploring ES6: Sets and Maps

So, in javascript everything is an Object right? Well, here are some more Objects with extended functionality, courtesy of ECMAScript 6.
Continuing, I will list what Sets and Maps provide us and try to make a couple small cases for why we would use either or both!

A quick preface from our favorite, MDN, describes a difference for Sets in comparison of the Set.has method and the Array.prototype.includes method and expresses that .has is faster "when an Array object has a length equal to a Set object's size."*

MDN also describes Maps advantages over Objects as thus: "A Map does not contain any keys by default. It only contains what is explicitly put into it" whereas the Object.prototype could result in "key collision" in some unfortunate cases.*

*See Works Cited for MDN references

I will cover the above mentioned methods, properties, and functionalities of Maps and Sets as follows:

SETS

Sets are collection objects with built in methods. They act similar to arrays in that they store values in order but they cannot be accessed in the same 0-index way.
mySet[0] // --> undefined
Values in a set are assigned value, value as their key, value pair correspondence. They will be stored in order of insertion.
What makes Sets interesting is that each value stored in a Set must be unique.

Set Methods:

  1. .add(value) - adds to end like .push
  2. .has(value) - will return true or false if the Set contains the value we are looking for
  3. .values() - will return an iterable of values in the Set
  4. .entries() - will return an iterable of [value, value] pairs for every value in the Set
  5. .delete(value) - will delete the value, value pair in the Set and return a Boolean value on success or failure.
  6. .clear() - will empty the Set
  7. .forEach(cb) - built in .forEach method which can receive a callback function
  8. .size - a property of a Set that will return a number representing the size of stored items upon reference

WHY?

Why make something sweet and simple like the Array a weird object like a Set? Well, one trick I really like is using the Set for DE-duping. If you have an array full of pesky duplicates you can pass that array as an argument to a Set with the 'new' keyword and voila! Now only unique values remain.

let myArray = [1, 2, 3, 4, 5, 5, 3]; // --> [1, 2, 3, 4, 5, 5, 3]
let mySet = new Set(myArray);        // --> Set(5) {1, 2, 3, 4, 5}
let unique = [ ...mySet ];           // --> [1, 2, 3, 4, 5]
Enter fullscreen mode Exit fullscreen mode

In the example above we use the spread operator to pass our Set back into an array for easy duplicate removal and conversion back from Set to Array.

// long array full of duplicates
let myArray = [1, 2, 1, 3, 1, 2, 4,
               5, 5, 4, 2, 1, 3, 2,
               1, 3, 4, 4, 5, 1, 2, 
               1, 5, 5, 1, 2, 1, 3];

// new empty Set
let mySet = new Set();
Enter fullscreen mode Exit fullscreen mode

Suppose you know ahead of time that you will need a collection of unique values, collect in a Set:

// forEach duplicates array, set.add method to populate...
myArray.forEach(el => mySet.add(el));

// output --> Set(5) {1, 2, 3, 4, 5}
// so clean!! :]
Enter fullscreen mode Exit fullscreen mode

MAPS

Maps are collection objects that store key, value pairs (like Objects). They differ in that a Maps keys can be any value, including functions or objects.

Map Methods:

  1. .set(key, value) - adds next key and value pair to Map
  2. .get(key) - will return the value connected to the target key
  3. .has(key) - will return a Boolean if Map contains target key
  4. .keys() - will return an iterable of keys in the Map
  5. .values() - just like keys but for values
  6. .entries() - returns an iterable of key, value pairs for every entry in the Map, it looks like this: [Map Entries] { [ {}, 'a' ], [ [], 'b' ], [ 1, 1 ], [ 2, 'two' ] }
  7. .delete(key) - just like the delete keyword for Objects it will delete the key, value pair at the target key
  8. .clear() - will empty the entire Map
  9. .forEach() - built in .forEach, it explains itself...
  10. .size - actually invokes getSize. This is my favorite feature because it effectively acts as Array.length but for something resembling an Object. It will return a number but doesn't need parens() to invoke.

WHY?

You're probably thinking, "cool, colin... thanks for taking something simple and making it confusing..." BUT, a collection like a Map will provide us extra functionality and in the right scenarios afford us an advantage, and as programmers we have a toolbelt of tactics and advantages so here is a scenario I find Maps to be beneficial...

const myObject = {};     // --> {}
const myMap = new Map(); // --> Map(0) {}

const a = {};
const b = {};
Enter fullscreen mode Exit fullscreen mode

Do you have any predictions of what will happen if we try to assign these empty objects as properties to an Object? What if we assign them to a Map?

myObject[a] = 'a'; // --> { '[object Object]': 'a' }
myObject[b] = 'b'  // --> { '[object Object]': 'b' }

myMap.set(a, 'a'); // --> Map(1) { {} => 'a' }
myMap.set(b, 'b'); // --> Map(2) { {} => 'a', {} => 'b' }
Enter fullscreen mode Exit fullscreen mode

The output on the right represents console.log(myObject) and console.log(myMap) respectively. As you can see, the Object assignment assumes our variables to be the same object and therefore overwrites the '[object Object]' property. With our Map, because each Key has to be unique, it knows to store these variables independently. The same thing would happen if we were using empty Arrays: a = [] and b = [] so Maps are good to store empty collections that we may populate later.

Thanks for reading my blog! I love the syntax sugar that is ES6 and the little tricks that they provide. As I discover more I will continue to catalogue them here. Happy coding!

WORKS CITED

(MDN)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map

Top comments (0)