We all know how quirky Javascript is, with all its sly ways and silent mischiefs. I encountered another such shenanigan of JS while using Maps. For those of you still living in ice age- YES, JavaScript supports Map (and Set) Data Structures ES6 on.
Before we see what motivated me to write this post, let's quickly brush up what JS has to offer in Maps:
- What is it? - Just an easier way to create an object of key-value pairs. Needless to say, it inherits Object prototype.
- How is it any different from Objects? - We get several functions to make our life easier.
Find the documentation on Maps here.
For the sake of this article, let me list out some basic functions that we will be using.
//creating a new Map
const ourMap = new Map();
//setting key-value pairs
ourMap.set("firstName", "Regina");
ourMap.set("lastName", "Phalange");
//getting value, given a key
const fullName = ourMap.get("firstName") + " " + ourMap.get("lastName");
//fullName-> "Regina Phalange"
//Size of the map - number of key-value pairs
ourMap.size;
//returns 2
When you try the above out on a browser's developer console, you will see something like this:
(Note the arrow mark notation of Map's key-value pairs)
Now, since Map is nothing but a data structure holding key value pairs, it feels quite intuitive to go ahead and set the key-value using the usual Object properties method. Something like this-
ourMap["profession"] = "Trader";
ourMap.age = 45;
//All these return true as the properties indeed get set.
//You can check as following:
console.log(ourMap.profession);
console.log(ourMap.age);
ourMap.size;
//2
The above also sets a key-value pair in ourMap
. But what happens when you fetch the size of the map???
BAM! It is still 2!
Then where on earth did ourMap
engulf the age
and profession
keys? Where did it fetch these from when we console logged it??
The answers to these are very similar to Who murdered my array in my previous post.
When we take a look at the map after all our fiddling, we see something like this:
The key-value pair ONLY when set through the getter-setter, populates the entry in the [[Entries]]
of the Map (note the arrowed key-value). When set through the object literals, it uses Prototypal Chaining and accesses the methods offered by the Object interface to set the key-values OUTSIDE the [[Entries]]
.
Consequently, ourMap.size
which has access to only the Map Entries counts only the firstName
and the lastName
.
I have been working on developing a game. While using the Map to store Game Level Statistics, I used the shorthand for key-values and went bonkers when the map size kept returning 0. Only after further digging did I realise what was happening. I went back to the documentation and realised, there was a clear disclaimer for such a behavior, specially for lazy developers like myself.
Lesson learnt?? ALWAYS read the documentation thoroughly!š„±š„±
Now that we know what's happening, why stop here? Let's have some fun with it...
A trick you can play on JS newbies:
const person = new Map();
person.set("firstName", "Regina");
person.set("lastName", "Phalange");
person.firstName = "Phoebe";
person.lastName = "Buffey";
console.log(person.get("firstName")); //Regina
console.log(person.firstName); //Phoebe
//And the left Phalange of my brain short-circuits!! XD
This can also be a potentially popular entry-level JS interview question to see if you got your fundas right.
P.S. Remember that you cannot use any of the map functions on attributes that you set through object literals.
Again, lesson learnt? Read the damn documentation well! Hope you learnt something out of this article. We can also extrapolate this behavior to other data structures in JS, including Sets and Arrays... The fundamental remains the same!
Until next time...š
Top comments (1)
Can't agree more, can't go wrong with MDN docs. When I first got into Maps, I think I was prone to a similar mistake. Thanks for sharing.