Maps vs Objects in ES6, When to use?
What is an applicable example of using Maps over objects?
I think you've given one good example already: You at least need to use Map
s when you are using objects (including Function objects) as keys.
in particular, "when would keys be unknown until runtime?"
Whenever they are not known at compile time. In short, you should always use a Map
when you need a key-value collection. A good indicator that you need a collection is when you add and remove values dynamically from the collection, and especially when you don't know those values beforehand (e.g. they're read from a database, input by the user, etc).
In contrast, you should be using objects when you know which and how many properties the object has while writing the code - when their shape is static. As @Felix has put it: when you need a record. A good indicator for needing that is when the fields have different types, and when you never need to use bracket notation (or expect a limited set of property names in it).
Use maps over objects when keys are unknown until run time, and when all keys are the same type and all values are the same type.
I have no idea why someone would write something so obviously wrong. I have to say, people are finding more and more wrong and/or questionable content on MDN these days.
Nothing in that sentence is correct. The main reason to use maps is when you want object-valued keys. The idea that the values should be the same type is absurd--although they might be, of course. The idea that one shouldn't use objects when keys are unknown until run time is equally absurd.
One of the difference between Map
and Object
is:
Map
can use complex data type as its key. like this:
const fn = function() {}
const m = new Map([[document.body, 'stackoverflow'], [fn, 'redis']]);
m.get(document.body) // 'stackoverflow'
m.get(fn) //'redis'
watch out: For complex data type, If you want to get the value, you must pass the same reference as the key.
Object
, it only accept simple data type(number
, string
) as its key.
const a = {};
a[document.body] = 'stackoverflow';
console.log(a) //{[object HTMLBodyElement]: "stackoverflow"}
I think that with ES2015's Map
only two reasons are left to use plain objects:
- You don't want to iterate over the properties of an object type at all
- or you do but the property order doesn't matter and you can distinguish the program from the data level when iterating
When is the property order unimportant?
- if you have only a single value and some functions that should be associated explicitly with it (like
Promise
- which is a proxy for a future value - andthen
/catch
) - if you have a struct/record-like data structure with a static set of properties known at "compile time" (usually structs/records aren't iterable)
In all other cases you might consider using Map
, because it preserves property order and separates the program (all properties assigned to the Map
object) from the data level (all entries in the Map
itself).
What are the drawbacks of Map
?
- you lose the concise object literal syntax
- you need custom replacers for JSON.stringyfy
- you lose destructuring, which is more useful with static data structures anyway