Maps vs Objects

ECMAScript 2015 introduced Maps to the language. If you've checked these out, you'll notice that Maps and Objects are very similar, but there are some subtle, yet important, differences. In summary these are:

  • objects have a prototype, maps don't. This means that maps can't utilise prototypal inheritance. This also means that maps can't be polluted by the prototype chain and thus don't suffer from the hasOwnProperty check which is required when utilising objects as maps.

  • object keys must be strings, maps can have keys of any value. This means that you could use other objects/functions as keys in a map.

  • objects don't have a known size, maps have a size property. This means you can lookup the number of entries in a map, but if you wanted this behaviour with an object you'd have to manually track the size.

  • iterating properties on an object is inconssitent in terms of the iteration order, maps have a consistent iteration order. For example, if an object had two properties a and b, iterating over those properties might return a then b, or b then a. In a map the order would always be a then b - assuming a was set before b.

Usage Advice

MDN gives the following advice for when to use Maps instead of objects:

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.

and also:

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

Examples

Here are some thoughts on how we can utilise the new Map object:

For storing configuration

A map seems ideal for storing configuration. The main benefit here is the fact that maps can't utilise prototypal inheritance and therefore can't be polluted by the prototype chain.

For storing custom user settings

A map also seems ideal for storing custom user settings. The main benefit of a map here is the size property. For example, with a map you can simply check the size of the map to determine if their are any custom user settings that need persisting.

if (user.settings.size) {
  // we have some user settings to persist
}

With an object you'd have to loop over the objects key's to determine this - or maintain your own size state.

let size = Object.keys(user.settings).filter((k) => user.settings.hasOwnProperty(k)).length;

if (size) {
  // we have some user settings to persist
}

Conclusion

ES6 introduced a lot of new features. Each of these features were introduced for a reason. Although, often new feature use cases aren't immediately obvious, so it's a good idea to spend some time thinking about these use cases and how these new features can help you in your day-to-day work.

Hopefully this article has given you some food for thought.

Further Reading