const - JS | lectureData Structures, Modern Operators & Strings

Maps - Fundamentals

Data Structures, Modern Operators & Strings

In the last lecture, we learned about sets. Let's now learn about another JavaScript data structure called maps. Let me start by telling you that maps are more useful than sets. So what exactly is a map?

Well, it's certainly not the same thing that we use in real-life to find our way around. Instead, in JavaScript, a map is a data structure that we can use to map values to keys.

Just like an object, data is stored in key-value pairs in maps. The big difference between objects and maps is that the keys can have any type in maps, which can be huge. That is, in objects, the keys are basically always strings. But in maps, we can have any type of key. It could even be objects, arrays, or other maps.

Let's now create our first map: a restaurant map. The easiest way to create a map is to create an empty map without passing any argument to the constructor function.

script.js
const restaurantMap = new Map();

To fill up the map, we can use the set method, which receives two arguments: the key and the value.

script.js
restaurantMap.set('name', 'Le Cadoret');

You can see that the set method is pretty similar to the add method that we had in sets. Both allow us to add a new element to the data structure. And, remember that we can use any data type that we want.

For example, let's say that the restaurant has two locations. We can have something like this:

script.js
restaurantMap.set(1, 'Paris, France');
restaurantMap.set(2, 'Lisbon, Portugal');

Calling the set method does not only update the map that it's called on, but it also returns the map.

script.js
console.log(restaurantMap.set(3, 'Firenze, Italy'));

MAPS - 1

The fact that the set method returns the updated map allows us to chain the set method like this.

script.js
/**
 * Each set method returns the updated map on which we can
 * call the next set method.
*/
restaurantMap
  .set('categories', ['Italian', 'Pizzeria'])
  .set('open', 11)
  .set('close', 23)
  .set(true, 'We are open ✅')
  .set(false, 'We are closed ❌');

To read data from a map, we use the get method. All we need to do is to pass in the name of the key.

console.log(restaurantMap.get('name'));
console.log(restaurantMap.get(true));

MAPS - 2

Not that when we get elements from a map, the data type of the key matters. Because if we try, for example

script.js
console.log(restaurantMap.get('true')); // undefined

We will get undefined.

Let's now have some fun with maps. In our restaurantMap, we have two boolean keys (true and false) and the open and close keys which are all kind of related.

Let's say we have the below current time:

script.js
// We will see how to get the current time in JavaScript later.
const currentTime = 21 // 9pm

We could now do something really clever like this:

script.js
/**
 * When doing restaurantMap.get(), if we pass in true we get We are open ✅, and if we pass in false we get We are closed ❌.
 *
 * So, in order to get the correct message according to time, we need to check the current time and see if it's between the open and close times.
*/
restaurantMap.get(currentTime > restaurantMap.get('open') && currentTime < restaurantMap.get('close')) // We are open ✅

MAPS - 3

Don't overuse this kind of pattern because although it's clever, it's not readable. This was just to show the power of booleans as map keys.

The next method we are going to learn is the has method. This method checks if a map contains a certain key.

script.js
restaurantMap.has('name'); // true
restaurantMap.has('open'); // true
restaurantMap.has('categories'); // true
restaurantMap.has('false'); // false
restaurantMap.has('true'); // false

We can also use the delete method to remove a key-value pair from a map.

script.js
restaurantMap.delete('name');
restaurantMap.has('name'); // false

Now comparing this to objects, we can also delete properties from objects using the delete operator. But that's a really slow process. And usually, it is not encouraged.

Next, maps also have the size property. This property returns the number of key-value pairs in the map.

script.js
// Remember that we deleted the name property. 😉
restaurantMap.size; // 7

To finish, we can use the clear method to remove all key-value pairs from a map.

script.js
restaurantMap.clear(); // Map(0) {}
restaurantMap.size; // 0

As you can see, there is some overlap in how we work with maps and sets. And that's because they were both introduced in ES6.

To finish this lecture, let me show you that we can, in fact, use arrays or objects as map keys.

Let's start by creating a new map.

script.js
const arraysObjectsMap = new Map();

Now let's add some key-value pairs to the map.

script.js
arraysObjectsMap.set([1, 2, 3], 'Array');

To get the data based on the above array, you might think that we would have to do something like this:

script.js
arraysObjectsMap.get([1, 2, 3]);

It would return undefined. That's because if you remember what we learned about primitives versus objects, in the previous chapter about how JavaScript works behind the scenes, the array passed in the set method and the array that is passed in the get method are two different objects.

Even though we wrote them in the same way and they have the same elements, they are not the same object in the heap. Thus, the key that we pass in the set method is the object in memory and not the one that we pass in the get method.

So, in order to make it work, we would have to do this.

script.js
const array = [1, 2, 3];
arraysObjectsMap.set(array, 'Array');
arraysObjectsMap.get(array); // Array

The above solution now works because, the array variable provided to the set and get methods refer to the same place in memory.