43

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?

| improve this question | | | | |
  • 4
    MDN, as usual, has a good comparison. – Chris Hayes Jun 5 '15 at 2:18
  • 1
    FYI, Map appears to be faster for both setting and getting. – mpen Feb 2 '16 at 17:46
  • @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 Sep 22 '16 at 16:14
  • @callum Uhh..no, not positive. You might want to write some new performance tests. – mpen Sep 22 '16 at 16:38
51

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.

| improve this answer | | | | |
  • 1
    What's the identity hashcode function used by Javascript? – Pacerier Sep 18 '17 at 22:47
  • 1
    @Pacerier === :) – gustavohenke Sep 19 '17 at 12:32
  • Maps are much faster than plain objects these days. – jayarjo Jun 8 '18 at 17:39
  • 2
    @gustavohenke You said it's === whereas it's SameValueZero in the context of the question. – lolmaus - Andrey Mikhaylov May 13 '19 at 15:20
  • 1
    @lolmaus-AndreyMikhaylov Well that's arguable. The person didn't ask explicitly about Maps. – gustavohenke May 15 '19 at 4:15
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.com/es6-map-vs-object-properties/243

| improve this answer | | | | |
  • 2
    That's not how you write performance tests. – Qix - MONICA WAS MISTREATED Aug 5 '17 at 22:00
  • 7
    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? – starlogodaniel Aug 7 '17 at 18:38
  • 9
    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. – Qix - MONICA WAS MISTREATED Aug 8 '17 at 5:38
  • 2
    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. – starlogodaniel Aug 9 '17 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 Nov 29 '19 at 16:11
3

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.

| improve this answer | | | | |
  • 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. – Gust van de Wal Jan 17 at 15:11

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