paint-brush
JavaScript Maps: Everything You Need to Knowby@smpnjn
564 reads
564 reads

JavaScript Maps: Everything You Need to Know

by Johnny SimpsonSeptember 27th, 2022
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

Javascript Maps are a great way to store data when you don't need all the flexibility of objects and things like the order of your data are incredibly important. They also prove more performant than objects in situations requiring frequent addition and removal of items.
featured image - JavaScript Maps: Everything You Need to Know
Johnny Simpson HackerNoon profile picture

You're probably familiar with Javascript Objects - but did you know there is another way to create sets of data in Javascript, known as Maps? You might be using Javascript plain old objects right now when a map may be a better solution to your problem.


Javascript maps differ in a few major ways from objects. Although typeof new Map() returns object, don't let that fool you! Here are some of the major differences from objects:


  • Does not contain any keys by default, unlike objects, which contain a prototype object.

  • They are guaranteed to be ordered by the order they were inserted. Objects are like this too these days, but they don't carry the same guarantee.

  • The keys of a map can be anything, including a function, or even an object. Whereas in Javascript, it must be a string or symbol.

  • They have better performance than objects on tasks that require rapid or frequent removal or addition of data.

  • They are iterable by default, unlike objects.


Given that maps have so many benefits, let's take a look at how they work.

The Basics of How Javascript Maps Work

Any map in Javascript is initiated using the new Map() constructor. For example, let's create a map called myFirstMap:

let myFirstMap = new Map();


The difference is to set, get, or delete keys from a map, you have to use specific methods that come along with Map. So to set a new value of someValue with the key firstKey, I can run the following method:

let myFirstMap = new Map();

myFirstMap.set('firstKey', 'someValue');

Deleting an Item in a Javascript Map

If we then wanted to delete a key in a Javascript map, we have to call the delete() method:

let myFirstMap = new Map();

myFirstMap.set('firstKey', 'someValue');
myFirstMap.delete('firstKey');


You can also delete the entire map altogether, leaving no items in it using clear():

let myFirstMap = new Map();

myFirstMap.set('firstKey', 'someValue');
myFirstMap.clear();
console.log(myFirstMap); // Returns Map(0)

Getting a Key in a Javascript Map

Similar in usage to the other methods, to get the value of firstKey, we have to use get():

let myFirstMap = new Map();

myFirstMap.set('firstKey', 'someValue');

myFirstMap.get('firstKey') // 'someValue'

Checking if a Key Exists in a Javascript Map

Javascript Maps also have a method called has(), if we want to check if a map has a certain key:

let myFirstMap = new Map();

myFirstMap.set('firstKey', 'someValue');

myFirstMap.has('firstKey') // true

Warning: Don't Use Typical Object Properties With Maps

Javascript is full of quirks, and maps are no different. Weirdly, maps can also support object notation. For example, this seems to work:

let myFirstMap = new Map();

myFirstMap['firstKey'] = 'someValue';

console.log(myFirstMap); // Map(0) { firstKey: 'someValue' }


However, you should not do this! This is not creating new entries in the map itself - you're simply creating an object. So you'll lose all the benefits of Javascript maps.

Telling How Big a Javascript Map Is

One other useful thing in which maps are a little easier to use than objects is finding out how many keys are in a map. For this, we can use the size() method, which returns the number of keys:

let myFirstMap = new Map();

myFirstMap.set('firstKey', 'someValue');

myFirstMap.size // 1


For objects, we typically use a mixture of Object.keys() and length to find out the size of an object:

let myObj = { "name" : "John" };
let sizeOfObj = Object.keys(myObj).length; // 1

Using Maps With Non-String Keys

As I mentioned, Javascript Maps allow non-conventional keys, like functions and objects, whereas objects only allow strings and symbols. For example, this is valid in a map:

let myFirstMap = new Map();
let myFunction = function() { return "someReturn"; }
myFirstMap.set(myFunction, "value");


Map keys are based on reference, not value. That means although the following will work:

let myFirstMap = new Map();
let myFunction = function() { return "someReturn"; }
myFirstMap.set(myFunction, "value");

myFirstMap.get(myFunction); // Returns "someReturn"


This will not:

let myFirstMap = new Map();
let myFunction = function() { return "someReturn"; }
myFirstMap.set(myFunction, "value");

myFirstMap.get(function() { return "someReturn"; }); // Returns undefined
myFirstMap.get('someReturn'); // Returns undefined


That's because although function() { return "someReturn"; } and myFunction are the same in value, they are not the same in terms of where they are stored in system memory. So they are not exactly equivalent. Similarly, maps do not work on return value - so myFirstMap.get('someReturn') also returns undefined.


The same example works for objects, with similar results:

let myFirstMap = new Map();
let myObject = { "someKey" : "someValue" }
myFirstMap.set(myObject, "value");

myFirstMap.get({ "someKey" : "someValue" }); // Returns undefined
myFirstMap.get(myObject); // Returns 'value'

Merging Javascript Maps

If you have multiple maps you want to merge into one, you can merge them in the same way you merge objects - with the spread syntax. For example, here I merge myFirstMap and mySecondMap into myNewMap using the spread syntax:

let myFirstMap = new Map();
myFirstMap.set("some", "value");
let mySecondMap = new Map();
mySecondMap.set("someOther", "value");

let myNewMap = new Map([...myFirstMap, ...mySecondMap]);

console.log(myNewMap);
// Map(2) { some: "value", someOther: "value" }

Iterating on a Map

As mentioned, maps are iterable by default. If we want to iterate over objects, we usually have to use a function like Object.keys. Ultimately this means we can use forEach on any map, like so:

let myFirstMap = new Map();
myFirstMap.set("some", "value");
myFirstMap.set("someOther", "value");

myFirstMap.forEach(function(value, key, map) {
    // value -> the value of that key in the map
    // key -> the key for this item in the map
    // map -> the entire map
    console.log(value, key, map);
})

Iterating on a Javascript Map Using For

You can also iterate on a map using for(let ... of )! If you do that, each item is returned as an array of the key and value. For example:

let myFirstMap = new Map();
myFirstMap.set("some", "value");

for(let x of myFirstMap) {
    // Returns [ 'some', 'value' ]
    console.log(x);
}

Iterating Over Values or Keys in Javascript Maps

Another cool way we can iterate over values or keys in Javascript is to use the values() or entries() methods. These return a new iterator for the values and items in a map respectively.


That means we can access the next key or value using next() functions, just like in generator functions.


For example, let's look at how entries() works:

let myFirstMap = new Map();
myFirstMap.set("some", "value");
myFirstMap.set("someOther", "value");
myFirstMap.set("aFinal", "value");

let allKeys = myFirstMap.entries();
console.log(allKeys); // Returns MapIterator {} object

console.log(allKeys.next()); // Returns { value: [ 'some', 'value' ], done: false }
console.log(allKeys.next().value); // Returns [ 'some', 'value' ]


Our return from allKeys.next() is an object. The value in this object is [ 'some', 'value' ] - an array of the first item in our map. We can keep running next() to get the following items in the map. Pretty cool! We can do the same thing again, with just values:

let myFirstMap = new Map();
myFirstMap.set("some", "value");
myFirstMap.set("someOther", "value");
myFirstMap.set("aFinal", "value");

let allValues = myFirstMap.values();
console.log(allValues); // Returns MapIterator {} object

console.log(allValues.next()); // Returns { value: 'value' done: false }
console.log(allValues.next().value); // Returns 'value'


Iterators like this prove useful in some specific situations and can be a cool way to iterate through all the data in your Map.

Serialization of Maps in Javascript

One of the drawbacks for some people, which maps have, is that they cannot be easily serialized with JSON.parse() and JSON.stringify. Trying to do so results in an empty object, and this kind of makes sense - since the object of a Map is empty if we only populate it with entries:

let myFirstMap = new Map();
myFirstMap.set("some", "value");
myFirstMap.set("someOther", "value");
myFirstMap.set("aFinal", "value");

// Returns {}
console.log(JSON.stringify(myFirstMap));


The only realistic way to serialize a Map is to convert it to an object or array, which simply means you'll have to maintain some separate helper functions to do this task for you, should you use Maps.


For example, we can use Array.from() to convert our Map to an array, and then use JSON.stringify() to serialize it:

let myFirstMap = new Map();
myFirstMap.set("some", "value");
myFirstMap.set("someOther", "value");
myFirstMap.set("aFinal", "value");

let arrayMap = Array.from(myFirstMap);

// Returns [["some","value"],["someOther","value"],["aFinal","value"]]
console.log(JSON.stringify(arrayMap));


Then, if we want to turn it back into a map, we have to use JSON.parse() in conjunction with new Map():

let myFirstMap = new Map();
myFirstMap.set("some", "value");
myFirstMap.set("someOther", "value");
myFirstMap.set("aFinal", "value");

// Turn our map into an array
let arrayMap = Array.from(myFirstMap);

// The JSON stringed version of our map:
let stringifiedMap = JSON.stringify(arrayMap);

// Use new Map(JSON.parse...) to turn our stringed map into a map again:
let getMap = new Map(JSON.parse(stringifiedMap));

// Returns Map(3) {'some' => 'value', 'someOther' => 'value', 'aFinal' => 'value'}
console.log(getMap);

Conclusion

Javascript Maps are a great way to store data when you don't need all the flexibility of objects and things like the order of your data are incredibly important. They also prove more performant than objects in situations requiring frequent addition and removal of items.


In this guide, we've covered everything you need to know about Maps, but if you want to learn more about Javascript click here.


Hope you've enjoyed this one - have a great day.