5 Reasons To Choose JavaScript Maps Over Objects For Storing Key-Value Pairs(With Examples)
Gus Pear 🍐

Gus Pear 🍐 @gustavupp

About: Self-taught Developer • I help you land your first dev job with posts on programming and self-mastery • @theguspear 🐦

Location:
Brisbane
Joined:
Oct 28, 2022

5 Reasons To Choose JavaScript Maps Over Objects For Storing Key-Value Pairs(With Examples)

Publish Date: Jan 21 '23
172 34

At 18 I started my "career" as an IT support guy.
At 20 I was flying 80 hours per month as a flight attendant.
At 22 I got my commercial airplane pilot license.
At 29 I was a carpenter and today at 32 I work as a software developer.

If there's one thing I know how to do well, it is how to keep up with changes. Because if you don't, you are left behind. I know firsthand how comfortable it is to use stuff you know by heart instead of giving the 'new' a try.

But discomfort is what makes you grow, as a human and as a dev.

Let's dive head first and see what the "newish" Map can teach us today.

What is the Map object?

Here's the holy source's (MDN) definition:

The Map object holds key-value pairs and remembers the original insertion order of the keys. Any value (both objects and primitive values) may be used as either a key or a value.

To put it simply, Map is JavaScript's native hash or dictionary data structure.

Syntax: Map vs Object

Here's a handy cheat sheet that does a great job at showing their syntax differences, posted by Andrej on Twitter.

Image description

He also recorded performance tests if you are interested.

Reason 1: You Won't Overwrite Default Keys By Accident

Map
By default, a Map does not contain any keys. It is a clean slate. It only has what you put into it.

Neither more nor less.

Image description

Object
Objects by default have their prototype, so it contains default keys that could potentially clash with your own keys.

This can be bypassed by passing null as the prototype when creating a new Object: Object.create(null)

Check out the difference:

  • New Object

Image description

  • New Object with null prototype

Image description

Reason 2: It Accepts Any Type As Key

Map
Maps accept any type of key. That includes functions, objects, and all primitives(string, number, boolean, symbol, undefined, null, and bigint).

let obj = { 'a': 'a' };
let func = () => 'hey';

//you can also initialize multiple values at once using array syntax
let map = new Map([[123, true], [true, 123], [obj, 'object'], [func, 'function']])

map.keys() // 123, true, Object, () => 'hey'
map.get(obj) // 'object'
map.get(func) // 'function'
map.get({ 'a': 'a' }) // undefined 
//Object and Functions are stored by reference, so { 'a':'a' } and obj are different objects)
Enter fullscreen mode Exit fullscreen mode

Object
Object's key must be either a String or a Symbol.

let obj1 = { 'a': 'a' };
let func = () => 'hey';

let obj = { 123: true, true: 123, obj1: 'object', func: 'function' };
Object.keys(obj) 
// ['123', 'true', 'obj1', 'func'] converts all keys to strings

obj[func] //undefined
obj['func'] // 'function'
Enter fullscreen mode Exit fullscreen mode

Reason 3: Maps Are Iterable

Map
Maps are natively iterable. That means you can loop over them with for of or .forEach() loops.

const map = new Map();
map.set(0, 'zero').set(1, 'one'); //you can chain .set()

for (const [key, value] of map) {
  console.log(`key: ${key}, value: ${value}`);
}
// key: 0, value: zero
// key: 1, value: one

//if you just want the 'values' or just the 'keys'
for (const key of map.keys()) { // or map.values()
  console.log(key);
}
// 0
// 1

map.forEach((value, key) => console.log(`key: ${key}, value: ${value}`));
// key: 0, value: zero
// key: 1, value: one
Enter fullscreen mode Exit fullscreen mode

Object
Objects are not iterable, even though you can iterate over them using for in and Object.Entries()

let obj = { 0: 'zero', 1: 'one' }

for(let key in obj){
    console.log(`key: ${key}, value: ${obj[key]}`)
}
// key: 0, value: zero
// key: 1, value: one

Object.entries(obj).forEach((item) => console.log(`key: ${item[0]}, value: ${item[1]}`))
// key: 0, value: zero
// key: 1, value: one

Enter fullscreen mode Exit fullscreen mode

Reason 4: Maps Can Be Merged With Arrays, And Converted To Arrays

Map
Maps are Arrays are 100% compatible, making it intuitive move from one to another.

Here's how you can convert a Map into an Array

let map = new Map([ [1, 'one'], [2, 'two'] ]);
Array.from(map) //[ [1, 'one'], [2, 'two'] ] exactly the same array you initially passed in

//or you can use the spread operator
const newArr = [...map];
Enter fullscreen mode Exit fullscreen mode

An Array into a Map

let arr = [ [1, 'one'], [2, 'two'] ];
new Map(arr); //{ 1 => 'one', 2 => 'two' }
Enter fullscreen mode Exit fullscreen mode

Here's how you can merge a Map and an Array

let map = new Map([ [1, 'one'], [2, 'two'] ]);
let arr = [3, 'three']

let combinedMap = new Map(...map, arr); 
// { 1 => 'one', 2 => 'two', 3 => 'three' }

let combinedArr = [...map, arr];
// [ [1, 'one'], [2, 'two'], [3, 'three'] ]
Enter fullscreen mode Exit fullscreen mode

Object
Concerting an Object into an Array

let obj = { 1: 'one', 2: 'two'};
Array.from(obj) // [] doesn't work

//you'd have to do
Array.from(Object.entries(obj))
//[ ['1', 'one'],['2', 'two'] ]

//or
[...Object.entries(obj)]
//[ ['1', 'one'],['2', 'two'] ]
Enter fullscreen mode Exit fullscreen mode

Reason 5: You Can Easily Check The Size

Map
Map has a built-in size property that returns its size.

let map = new Map([1, 'one'], [true, 'true']);
map.size // 2
Enter fullscreen mode Exit fullscreen mode

Object
To check the size of an object you have to combine Object.keys() with .length

let obj = { 1: 'one', true: 'true' };
Object.keys(obj).length // 2
Enter fullscreen mode Exit fullscreen mode

The downside? No Native Method For Serialization And Parsing

Map
Maps have no native support for serialization or parsing to and from JSON.

The documentation suggests implementing your own by using the replacer argument that can be passed to JSON.stringify(obj, replacer) and the reviver argument passed to JSON.parse(string, reviver)

You can find the suggested implementation here

Object
You can natively serialize and parse an Object to and from JSON using JSON.stringify() and JSON.parse() respectfully.

2 Examples of how you can replace Object with Map

#1 Calculating the total price and items of an eCommerce shopping cart

This is one of the examples from the Complete Guide To JavaScript .reduce() Function

Given the following array

const shoppintCart = [
  { price: 10, amount: 1 },
  { price: 15, amount: 3 },
  { price: 20, amount: 2 },
]
Enter fullscreen mode Exit fullscreen mode

We want to return an Object like { totalItems: 6, totalPrice: 45 }

This is the original code

shoppintCart.reduce(
  (accumulator, currentItem) => {
    return {
      totalItems: accumulator.totalItems + currentItem.amount,
      totalPrice:
        accumulator.totalPrice + currentItem.amount * currentItem.price,
    }
  },
  { totalItems: 0, totalPrice: 0 } //initial value object
)
// { totalItems: 6, totalPrice: 45 }
Enter fullscreen mode Exit fullscreen mode

This is a version using Map

shoppintCart.reduce(
  (accumulator, currentItem) => {
      accumulator.set('totalItems', accumulator.get('totalItems') + currentItem.amount);
      accumulator.set('totalPrice', accumulator.get('totalPrice') + currentItem.price);
      return accumulator;
  },
  new Map([['totalItems', 0], ['totalPrice', 0]])
)
// { 'totalItems' => 6, 'totalPrice' => 45 }
Enter fullscreen mode Exit fullscreen mode

#2 A Different Way To Remove Duplicate Objects From An Array

This is a piece of code I actually used in the bookshelf app I made when I started learning JavaScript.

Googling about how to remove duplicate objects from an array led me to the example I share below.

This is an array with one duplicate object

const books = [
  { id: 1, title: 'How To Win Friends And Influence People', author: 'Dale Carnegie' },
  { id: 1, title: 'How To Win Friends And Influence People', author: 'Dale Carnegie' },
  { id: 2, title: 'The Alchemist', author: 'Paulo Coelho' },
]
Enter fullscreen mode Exit fullscreen mode

Here's a peculiar way to remove the duplicate:


const uniqueObjsArr = [
   ...new Map(books.map(book => [book.id, book])).values()
];
Enter fullscreen mode Exit fullscreen mode

There is a bit too much happening on the above one-liner.
Let's break it down into chunks so it is easy to digest.


// 1. map the array into an array of arrays with `id` and `book`

const arrayOfArrays = books.map(book => [ book.id, book ])
// arrayOfArrays:
/*
[ 
   [ 1, {id: 1, title: 'How To Win Friends And Influence People', author: 'Dale Carnegie' } ],
   [ 1, {id: 1, title: 'How To Win Friends And Influence People', author: 'Dale Carnegie' } ],
   [ 2, { title: 'Alchemist', author: 'Paulo Coelho' } ]
]
*/

// 2. The duplicate is automatically removed as keys have to be unique

const mapOfUniqueObjects = new Map(arrayOfArrays)
// mapOfUniqueObjects: 
/*
{
   1 => {id: 1, title: 'How To Win Friends And Influence People', author: 'Dale Carnegie'},
   2 => { title: 'Alchemist', author: 'Paulo Coelho' }
}
*/

// 3. Convert the values back into an array.

const finalResult = [...mapOfUniqueObjects.values()];
// finalResult:
/*
[
   {id: 1, title: 'How To Win Friends And Influence People', author: 'Dale Carnegie'},
   {id: 2, title: 'The Alchemist', author: 'Paulo Coelho'}
]
*/
Enter fullscreen mode Exit fullscreen mode

Conclusion

If you need to store key-value pairs(hash or dictionary) use Map.

If you're only using string-based keys and need maximum read performance, then objects might be a better choice.

Other than that, use whatever you want because, at the end of the day, this is just a blog post of a random dude on the internet Lol.

Here's what we covered:

  • What is the Map object?
  • Syntax: Map vs Object
  • Reason 1: You Won't Overwrite Default Keys By Accident
  • Reason 2: It Accepts Any Type As Key
  • Reason 3: Maps Are Iterable
  • Reason 4: Maps Can Be Merged With Arrays, And Converted To Arrays
  • Reason 5: You Can Easily Check The Size
  • The downside? No Native Method For Serialization And Parsing
  • 2 Examples of how you can replace Object with Map

Thanks for reading!

If you like this article:

*Leave a comment below(You can just say hi!)
*Follow me on Twitter@theguspear

Catch you later,

Gus.

Comments 34 total

  • Tracy Gilmore
    Tracy GilmoreJan 21, 2023

    Hi Gus,
    Using a Map over an Object is very often a wise choice but for some reason one I seldom employ; I have no justification other than set in my ways.
    One thing to consider is JSON, Objects are supported directly but Maps are not.
    Regards, Tracy

    • Gus Pear 🍐
      Gus Pear 🍐Jan 22, 2023

      Hey Tracy! Good to see you here.

      The same goes for me. That is one of the reasons why I wrote the post haha.

      There is also the case where most of your colleagues might not be used to it, than you'd prefer to stick with regular objects not to raise eyebrows haha..

      Thanks for stopping by again, and have a great week!

  • Elliot Brenya sarfo
    Elliot Brenya sarfoJan 21, 2023

    Great post, it's clear that you have a lot of experience and knowledge about the topic. Your examples and explanations make it easy to understand the differences between Map and Object.

    Have you tried experimenting with the different use cases of Map and Object in your projects? It would be great to see some examples of how you have utilized these data structures in your own work.

    • Gus Pear 🍐
      Gus Pear 🍐Jan 22, 2023

      Hey Elliot! how are you? Thanks for taking the time to comment!

      I am not that experienced at all lol. I am just curious.

      And yes I have used it a few times. The second example at the end of the post is actual code I used in a project I build when buidling my portfolio.

      Have a great week man!

  • leob
    leobJan 22, 2023

    Isn't speed/performance another reason to prefer Map? I've heard that Map is faster with lookups, especially when the number of items is larger.

    • Gus Pear 🍐
      Gus Pear 🍐Jan 22, 2023

      Hey Leopb! how are you? thanks for leaving a comment!

      You're right, Map seems to be faster in most cases, specially for reading.

      There is a video in the first section with some tests.

      Have a great week my dude!

      • peerreynders
        peerreyndersJan 23, 2023

        The video doesn't actually cover a map.get(key: string) vs objectMap.key access comparison.

        Given the impact that performance of the object.property lookup has on the overall JS runtime performance I would be surprised if map.get(key: string) is faster than object.property for lookup over a [key, value] set not exceeding the size of the number of properties found on a typical object.

        Map is optimized for [key, value] deletion and insertion (while maintaining the insertion order for iteration which is something objects per spec don't guarantee even though they often do) and efficiently handling larger [key, value] sets.

        Meanwhile an object literal lookup will often perform similar to a switch statement on a string value.

        • Gus Pear 🍐
          Gus Pear 🍐Jan 23, 2023

          Hey Peerreynders! Thanks for you insighful comment!

          Apperantly Map outperforms Object in all operations unless you have small integer, array-indexed keys according to this article that run multiple tests.

          Have an awesome week!

          • peerreynders
            peerreyndersJan 24, 2023

            The article discusses insertion, deletion, and iteration performance, the scenarios Map is specifically optimized for. Lookup/access performance isn't discussed.

            In this test objects are faster on Chrome 109 (V8) while maps are faster on Firefox 109.0 (SpiderMonkey). But once the number of entries increases to 20-30 map performance catches up.

            • Gus Pear 🍐
              Gus Pear 🍐Jan 24, 2023

              I didn't know about the jsbench website! Thanks for sharing the link Peerreynders!

              That is an in-depth test.

              Thanks once again.

  • Easyjobber : le site de jobbing en France
    Easyjobber : le site de jobbing en FranceJan 22, 2023

    Great post with good examples and explanations

    • Gus Pear 🍐
      Gus Pear 🍐Jan 22, 2023

      I am super glad you found it useful Easyjobber!

      Passe une bonne semaine!

  • Andre Hammons
    Andre HammonsJan 22, 2023

    Thank you for the post! I don't didn't really understand the difference until reading this. I definitely assumed they were the same thing.

    • Gus Pear 🍐
      Gus Pear 🍐Jan 22, 2023

      I am happy to hear that my post helped to clarify the differences Andre!

      That is what makes my day.

      Thanks for taking the time to leave a comment and have an awesome week.

  • Fakie Tap
    Fakie TapJan 22, 2023

    Nice explanation. Maps don't allow duplicates. Which is a good reason to use them sometimes.
    Did not known about new object(null)
    Good to know.

    Thanks

    • Gus Pear 🍐
      Gus Pear 🍐Jan 23, 2023

      Hey Frakie Tap! I am glad you got some value out of it.

      Thanks for taking the time to leave a comment!

      have a great week my dude

  • Ebenezer Enietan (Niza)
    Ebenezer Enietan (Niza)Jan 23, 2023

    Nice work Gus,
    I imagine using a map with my key and/or values as functions if the exact their values needs to be calculated at a later time in my logic?... still thinking

    • Gus Pear 🍐
      Gus Pear 🍐Jan 23, 2023

      Hey Niza!! thanks for leavaving a comment man!

      Not 100% sure what you mean though.. haha

      Have a great week man

  • Rense Bakker
    Rense BakkerJan 23, 2023

    Great post! No native serialization is a big downside though. In modern apps, a lot of data structures go from/to Json APIs, so having data structures with native serialization is extremely convenient. The benefits are there, but only for data that doesn't need to be serialized I think.

    • Gus Pear 🍐
      Gus Pear 🍐Jan 23, 2023

      Hey Rense! thanks for stopping by.

      100% with you, no native serialization/parsing is a big downside. That's one of the reasons I'd choose plain objects.

      Have a great week!

  • Ernazar
    ErnazarJan 23, 2023

    Thanks

    • Gus Pear 🍐
      Gus Pear 🍐Jan 23, 2023

      Thank you Ernazar for leaving a comment!

  • Bidisha Das
    Bidisha DasJan 24, 2023

    One of the best articles so far. Was waiting for this.

    • Gus Pear 🍐
      Gus Pear 🍐Jan 24, 2023

      Wow, you just made my day Bidisha!

      I am glad it was helpful!

      See you around.

  • Alwaisy al-waisy
    Alwaisy al-waisyJan 25, 2023

    map is more like an array and modern data type.

  • Franco
    FrancoJan 26, 2023

    Very nice article, thanks a lot! I will use Map and see how that goes.

    • Gus Pear 🍐
      Gus Pear 🍐Jan 28, 2023

      I am happy that you liked it Franco! Come back and let me know how it went

  • Raí B. Toffoletto
    Raí B. ToffolettoJan 26, 2023

    Great research and article 🎉

  • Yamiteru
    YamiteruJan 28, 2023

    Hey I think you've missed a very important point.

    Under the hood objects strongly favor static vs dynamic shapes/size. This means that adding or deleting keys in objects is very slow compared to maps which are designed for exactly this.

  • Kumar Kalyan
    Kumar Kalyan Jan 30, 2023

    Helpful article @gustavupp

  • baris-roboplas
    baris-roboplasAug 1, 2023

    except for a few things(non-technical), great post and also great informative comments

Add comment