DEV Community

Cover image for Why to use Maps over Objects in JS ?

Why to use Maps over Objects in JS ?

faisal khan on October 07, 2021

In JavaScript, an object is a standalone entity, with properties and type. Compare it with a cup, for example. A cup is an object, with propertie...
Collapse
 
blackr1234 profile image
blackr1234 • Edited

May I ask some questions which may seem silly:

Q1a: Why are you not providing the value when you call selectedItems.set in your Map practical example?

Q1b: Since you are not providing the value, could you simply use an array or Set of strings in your Map practical example? If you need helper methods, Set does have add and delete.

Q2: When you talk about performances of object deletion vs map entry deletion, you do not provide figures or references. Could you elaborate more on it please? I can't imagine why deleting a key from an object will have performance issue.

Update:

I see your conversation with LUKESHIRU and I think you use Map over an array or Set mainly because of performance ("scalability") as the Map implementation in V8 is a hash map. I think you should include this in your article stressing that performance is a huge consideration (at least in your practical example) because "why not an array or Set" may be the first thing people think of when they read your Map practical example. Otherwise, it is a great article!!

However, it will only be an issue when you have tons of records inside the array or Set of selected items I guess (I did not test it) when you navigate between the rightmost pages or pages without selection and it does lookups in O(N) multiple times. In this case, without using a Map, I think we can have an array of array/Set of strings, where the first layer of array is the page number and the second layer is the selected items on that page. I think it should perform pretty well, but to obtain a flat list of strings, we will need to flat map the array.

Collapse
 
faisalpathan profile image
faisal khan

Thanks @blackr1234 , yup i will try and include the performance specific point as well.

Whenever i have to render items and want to do a lookup to a variable to get an idea about what states need to render, i usually start with using array's and then gradually move to either objects or maps depending upon the use-case(this always happens post profiling session).

 
faisalpathan profile image
faisal khan • Edited

Thanks for commenting

  1. The point here was Map solves this purpose, i am not trying to showcase that Objects are inferior to Maps, but Maps are designed to solve some loopholes which were initially created, and Maps does it without looping over the keys

  2. We need length of objects, it a simple clash between what you feel is ideal and what is real, ideal world !== real world. Why i wrote the problem is because multiple dev would have faced it, and its not wrong to do it with .entries or .keys, but if we have a data structure which does not allow you doing any of those stuffs and gives to the length in o(1) then why not use it in such condition ?

  3. It was a point to consider, some devs already know it, but there can be problem if someone is not aware of the inherited methods, hence my point. Again Maps does not have this, its pretty safe to use was my answer to this.

  4. I liked the way the spread works, i forgot about it, its a good point, how this this work if i want to delete nested keys ?

Now coming to your another solution for the example. Here we have no backend dependency. Backend will always give us array of objects to render as rows in the table.

The point here is what happens when you select a row or what happens when you click on select all on the header. You are using a array to maintain selected items which is correct no issues in small or moderate list.

My point over here is when re-rendering the list again, post select-all is clicked, every row while rendering will have to make a lookup to the selected list array, to know if we want to render a selected state or not. This is simply a O(n) lookup done by each row to either show or not show selected state.

Which is solved by either objects or Maps which is done in O(1)

Last but not the least, its just wonderful to have conversation on a topic, since i am trying to constantly learn myself, and learn from my mistakes. Its was a great conversation @lukeshiru , i learnt a lot from our conversation.

Cheers!

Collapse
 
faisalpathan profile image
faisal khan

Thanks for commenting, the answer to your points are as follows:

  1. Only string or symbol could be used as key: but looping over the object to achieve this is what i feel is not ideal scenarios. At the same time as per your solution it is not possible to have one key as number and other key as string in the same object

  2. No proper helper methods to work with objects: In day to day scenarios, i have build multiple features and it was my major requirement where i needed to find the length of the object, moreover helper methods which maps provides easily surpasses all my needs i expected from object.

  3. Own object properties might collide with property keys inherited from the prototype: I agree with you, but this is both curse and boon for me, when we develop a feature we normally do not use toString in-order to customize its behaviour, but a the same time if someone overwrites the methods it can cause problems when it was not intended.

  4. Deleting keys causes problem in large objects: Mutations are evil i agree, but how do you remove a key from a copied object ? i am happy to have a conversation on this

Now coming to the solution you have given to me on the example, the problem with your solution is scalability

As per your solution when we select all the items from the list we have to add all the items in an array of items.

But when we are rendering selected state on each of the row we have to traverse the complete array to find out if the value exists in the selectItems list or not, which is O(n), why this matter is assume you having 1000 rows and you are traversing your selectedList array 1000 times to show selected state on the row

But when we use an objects or maps it is O(1).

Cheers!

Collapse
 
assertnotnull profile image
Patrice Gauthier

For omitting a property of an object there is ramdajs.com/docs/#dissoc
and ramdajs.com/docs/#dissocPath for nested properties.
Once you get familiar with this lib you see the potential it has

Collapse
 
supportic profile image
Supportic

Cannot read maps as config files like json or yaml files.

Collapse
 
faisalpathan profile image
faisal khan

Good point thanks

Collapse
 
petermortensen profile image
Info Comment hidden by post author - thread only accessible via permalink
Peter Mortensen • Edited

All or part of this is plagiarised. A dead giveaway is the high level of English in the body and a title in broken English (currently "Why to use Maps over Objects in JS ?") - incl. the presence of the Indian space. A priori it is a very unlikely high level of English.

For instance, plagiarised from Stack Overflow question "Map vs Object in JavaScript", near "are only using string-based keys and need maximum read performance" (exact match). An even better match is with revision 10 (that answer has since been modified).

Collapse
 
darrylnoakes profile image
Darryl Noakes

You can iterate over the keys of an object using for ... in. Same as you can ierate over the indices (i.e. keys) of an array.

Collapse
 
faisalpathan profile image
faisal khan

Thanks for commenting, i agree, but i don't prefer using for ... in, since i have to also have a check in place using .hasOwnProperty to find only the properties and methods you assigned to the object.

 
js_bits_bill profile image
JS Bits Bill

Gotcha. Is there an argument to be made to accept small levels of mutability with good documentation in order to avoid what could be large amounts of overhead or extra frameworks in practicing 100% immutability? I feel like it may add more complexity than necessary for smaller projects.

Collapse
 
danwalsh profile image
Dan Walsh

Super interesting stuff. With Redux strongly advising against using Maps in state, are there any options to work around this?

Collapse
 
faisalpathan profile image
faisal khan

We can create a custom middleware in redux to serialize maps, but the conditon is the key has to serializable.

Collapse
 
sebbdk profile image
Sebastian Vargr • Edited

In 15 years, I never strictly needed to use a map type in JS, or found object being a performance bottleneck.

I can imagine a few edge cases where it would make sense, but apart from that KISS. :)

Collapse
 
sativ01 profile image
sativ01

In my 5y career I'm using Maps at least couple of times per year.
I replace arrays that are often searched through using Array.find()
Check your projects, maybe there's a use case too

Collapse
 
sebbdk profile image
Sebastian Vargr

hmm maybe, i think the most use-cases for this i have are usually state related, and since i want state to be serialisable into json, i would have to make conversion to/from maps to get the benefit. :/

Do you have any none state related examples i can use to think about this?

Collapse
 
sativ01 profile image
sativ01

One major thing not mentioned here is that Maps are ordered.
If order matters, then there's not much choice.

Collapse
 
js_bits_bill profile image
JS Bits Bill

@lukeshiru
Wouldn't map.delete(key) be considered a mutation? Why is delete obj.key an evil mutation but not deleting from a map?

 
js_bits_bill profile image
JS Bits Bill • Edited

Thanks for clarifying. But if delete and map.delete() are both evil mutations, then what's the answer?

Collapse
 
aspiiire profile image
Aspiiire

Well, this is a Great article, thanks for sharing :D

Some comments have been hidden by the post's author - find out more