49

Plain object keys must be strings, whereas a Map can have keys of any type.

But I have little use for this in practice. In nearly all cases, I find myself using strings as keys anyway. And presumably new Map() is slower than {}. So is there any other reason why it might be better to use a Map instead of a plain object?

4
  • 7
    MDN, as usual, has a good comparison. Commented Jun 5, 2015 at 2:18
  • 2
    FYI, Map appears to be faster for both setting and getting.
    – mpen
    Commented Feb 2, 2016 at 17:46
  • 1
    @mpen – jsperf is down now. Are you sure map.set('foo', 123) performed quicker than obj.foo = 123? If so that's very surprising
    – callum
    Commented Sep 22, 2016 at 16:14
  • @callum Uhh..no, not positive. You might want to write some new performance tests.
    – mpen
    Commented Sep 22, 2016 at 16:38

3 Answers 3

55

There are some reasons why I prefer using Maps over plain objects ({}) for storing runtime data (caches, etc):

  1. The .size property lets me know how many entries exist in this Map;
  2. The various utility methods - .clear(), .forEach(), etc;
  3. They provide me iterators by default!

Every other case, like passing function arguments, storing configurations and etc, are all written using plain objects.

Also, remember: Don't try to optimize your code too early. Don't waste your time doing benchmarks of plain object vs Maps unless your project is suffering performance problems.

7
5

I'm not sure about this, but I think that performance is NOT a reason to use Maps. Take a look at this updated jsperf page:

http://jsperf.com/es6-map-vs-object-properties/73

It looks like (when dealing with strings at least) objects are much faster than maps for basic setting and getting.

EDIT: this answer is now outdated and wrong. See comment stream below.

EDIT2: Oddly, after all of the comments, it seems to return to Object being faster than Map (at least when storing numeric values). https://jsperf.app/es6-map-vs-object-properties/243

EDIT 3: It turns out JS optimizes everything when using a key that looks like a number, even if it was created as a string. When I use key_${i} rather than just ${i} for the key, things turn out much differently. Compare the flawed test above to this corrected version: https://jsperf.app/es6-map-vs-object-properties/251

12
  • 2
    That's not how you write performance tests. Commented Aug 5, 2017 at 22:00
  • 15
    That's not how you write useful comments. Please feel free to elaborate if you have an alternate methodology to suggest. What, specifically, is wrong with how those tests were written? Are they in any way invalid or unhelpful? Commented Aug 7, 2017 at 18:38
  • 11
    Language semantics/constructs being tested via microbenchmarks must only differ by one variable. Your tests vary across number of iterations, and a few of them will have their inner loop contents optimized out since the result is unused. Some tests pre-declare variables while others have the variable declaration inline with the for loop - which may incur different performance abnormalities. Commented Aug 8, 2017 at 5:38
  • 3
    Ouch, you're absolutely right. In my defense, the my version was an improvement on the one before it, but I missed both the pre-declare and the inner loop contents being optimized out. I was working with a colleague who improved upon my draft and I think resolved those issues: jsperf.com/es6-map-vs-object-properties/88. However, I think that it's valid to have different loop styles for the different data structures; in real usage, people will choose the loop structure with the best performance, and Map and Object have different "optimal" loop structures. Anyway, thanks for the catch. Commented Aug 9, 2017 at 15:12
  • 2
    Objects can never be as fast as Map. The runtime has to support prototypal inheritance & key mapping (e.g. numbers are converted to strings) that make optimizations complicated and bring overhead. Where as Map is just a straight forward key, value store that can be optimized to the extreme
    – sod
    Commented Nov 29, 2019 at 16:11
4

The other answers don't mention one last difference between objects and Maps:

The Map object holds key-value pairs and remembers the original insertion order of the keys.

Thus, when iterating over it, a Map object returns keys in order of insertion.

Quote from MDN, emphasis mine


This was the main reason I decided to use Map for the first time in a recent project. I had a normal object that I needed to display in a <table>, with each property going in a specific row.

let productPropertyOrder = [ "name", "weight", "price", "stocked" ];

let product =
{
    name: "Lasagne",
    weight: "1kg",
    price: 10,
    stocked: true
}

I wrote a function to transform an object into a Map according to a desired key order:

Note: this function discards all object properties not found in order

function objectToMap( obj, order )
{
    let map = new Map();

    for ( const key of order )
    {
        if ( obj.hasOwnProperty( key ) )
        {
            map.set( key, obj[ key ] );
        }
    }

    return map;
}

Then the map could be iterated over in the desired order:

let productMap = objectToMap( product, productPropertyOrder );

for ( const value of productMap.values() )
{
    let cell = document.createElement( "td" );
    cell.innerText = value;
    row.appendChild( cell );
}

Of course this is a bit contrived because one could just as well display when iterating over the property order without creating a Map in the process:

for ( const key of productPropertyOrder )
{
    if ( product.hasOwnProperty( key ) )
    {
        let value = product[ key ];
        // create cell
    }
}

But if you have an array of such objects and are going to be displaying them many places, then converting them all to maps first makes sense.

2
  • 1
    Your function objectToMap is reducing; every entry in the object whose key isn't in order, gets omitted from the resulting map. You might wanna include this information in your answer. Commented Jan 17, 2020 at 15:11
  • 3
    Objects also preserve the original insertion order of keys... mostly, but with some caveats: "array index" keys (which are those satisfying `${key>>>0}` === key) are always listed first, in numerical order, then all string keys in original insertion order, and then all symbol keys in original insertion order.
    – Matthijs
    Commented Oct 8, 2020 at 0:22

Not the answer you're looking for? Browse other questions tagged or ask your own question.