85
votes

Ref: MDN Maps

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.

Use objects when there is logic that operates on individual elements.

Question:

What is an applicable example of using Maps over objects? in particular, "when would keys be unknown until runtime?"

var myMap = new Map();

var keyObj = {},
    keyFunc = function () { return 'hey'},
    keyString = "a string";

// setting the values
myMap.set(keyString, "value associated with 'a string'");
myMap.set(keyObj, "value associated with keyObj");
myMap.set(keyFunc, "value associated with keyFunc");

console.log(myMap.get(keyFunc));
6
Yeah I noticed that. As I set a function as a value. @JonathanLonowski can you think of when I should do that tho :( it's tough thinking of usecases.Armeen Harwood
You might use it where you have say a DOM element that you want to associate some data with using an Object. Instead of using, say the element's ID as the key in an object, you can use the element itself as a key in a Map so you don't care whether the element has an ID (or any other unique identifier other than an object reference) or not.RobG
@RobG just a little addition: in that case it's a WeakMap that might also be helpful.zerkms
I think this suggests to use objects as/for records and Maps for every other kind of mapping. With records I mean a data struct with a fixed set of fields, such as a user object which has the fields name and id for example.Felix Kling
When I was reading that MDN page, the bullet-point list of use cases was much more helpful than the paragraph you quoted. Certainly in relation to the question posed in your title.CodingIntrigue

6 Answers

53
votes

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 Maps 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).

27
votes

I think that with ES2015's Map only two reasons are left to use plain objects:

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 - and then/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
10
votes

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.

5
votes

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"}
3
votes

Objects are similar to Maps in that both let you set keys to values, retrieve those values, delete keys, and detect whether something is stored at a key. Because of this (and because there were no built-in alternatives), Objects have been used as Maps historically; however, there are important differences that make using a Map preferable in certain cases:

  • The keys of an Object are Strings and Symbols, whereas they can be any value for a Map, including functions, objects, and any primitive.
  • The keys in Map are ordered while keys added to object are not. Thus, when iterating over it, a Map object returns keys in order of insertion.
  • You can get the size of a Map easily with the size property, while the number of properties in an Object must be determined manually.
  • A Map is an iterable and can thus be directly iterated, whereas iterating over an Object requires obtaining its keys in some fashion and iterating over them.
  • An Object has a prototype, so there are default keys in the map that could collide with your keys if you're not careful. As of ES5 this can be bypassed by using map = Object.create(null), but this is seldom done.
  • A Map may perform better in scenarios involving frequent addition and removal of key pairs.

MDN

2
votes

This question is a duplicate of but until it's closed, here's my answer from over there:

In addition to the other answers, I've found that Maps are more unwieldy and verbose to operate with than objects.

obj[key] += x
// vs.
map.set(map.get(key) + x)

This is important, because shorter code is faster to read, more directly expressive, and better kept in the programmer's head.

Another aspect: because set() returns the map, not the value, it's impossible to chain assignments.

foo = obj[key] = x;  // Does what you expect
foo = map.set(key, x)  // foo !== x; foo === map

Debugging maps is also more painful. Below, you can't actually see what keys are in the map. You'd have to write code to do that.

Good luck evaluating a Map Iterator

Objects can be evaluated by any IDE:

WebStorm evaluating an object