Suggest an editImprove this articleRefine the answer for “Map vs object”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**An `Object` is a general purpose structure for properties keyed by strings or symbols, while a `Map` is a specialized collection of "key to value" pairs with keys of any type and preserved insertion order.** In a `Map` a key can be an object or a function, the size is read through `.size`, the collection is iterated directly with `for...of`, it is faster under frequent inserts and deletes, and it inherits nothing from `Object.prototype`, so built in names never clash with keys. ```javascript const keyObj = { id: 1 }; const obj = {}; obj[keyObj] = 'object value'; console.log(obj); // { "[object Object]": "object value" } const map = new Map(); map.set(keyObj, 'map value'); console.log(map.get(keyObj)); // "map value" ``` **Key point:** use an object for a static model with known fields, use a `Map` for dynamic collections, caches and keys of arbitrary type.Shown above the full answer for quick recall.Answer (EN)Image**Many people assume that a `Map` and a plain object `{}` are almost the same thing, but there are substantial differences between them.** An `Object` is a general purpose data structure for storing properties whose keys are strings or symbols, while a `Map` is a specialized collection for storing "key to value" pairs with keys of any type and preserved insertion order. ## Theory ### TL;DR - Object keys are **strings and symbols only**, `Map` keys are **any values**. - A `Map` always returns elements **in insertion order**, an object sorts integer like keys. - Size: `Object.keys(obj).length` versus a plain `map.size`. - A `Map` is directly iterable with `for...of`, an object is not. - A `Map` is faster under frequent inserts and deletes. - A `Map` does not inherit from `Object.prototype`, so there are no clashes with `toString` or `hasOwnProperty`. - Conversion works both ways: `new Map(Object.entries(obj))` and `Object.fromEntries(map)`. ### Quick example ```javascript const obj = {}; const map = new Map(); const keyObj = { id: 1 }; obj[keyObj] = 'object value'; map.set(keyObj, 'map value'); console.log(obj); // { "[object Object]": "object value" } console.log(map.get(keyObj)); // "map value" ``` In the object the key turned into the string `"[object Object]"`, while in the `Map` it stayed a **real object**. If we added a second object as a key, in `obj` it would simply overwrite the first entry, because the resulting string would be identical. ### Key types | Feature | `Object` | `Map` | | --- | --- | --- | | Keys | Strings or symbols only | Any type (strings, numbers, objects, functions and so on) | This is the most important practical difference: only a `Map` lets you use an object or a function as a key and thereby attach data to a specific instance. ### Order, size and iteration **Key order.** | Feature | `Object` | `Map` | | --- | --- | --- | | Key order | Partly guaranteed (ES6 and later) | Always preserved | A `Map` always returns elements **in insertion order**, while an object behaves differently with numeric keys: ```javascript const obj = { 2: 'b', 1: 'a' }; console.log(Object.keys(obj)); // ["1", "2"] (numbers are sorted ascending) ``` ```javascript const map = new Map([[2, 'b'], [1, 'a']]); console.log([...map.keys()]); // [2, 1] (order is preserved) ``` **Size.** | Feature | `Object` | `Map` | | --- | --- | --- | | Size | `Object.keys(obj).length` | `map.size` | ```javascript const map = new Map([['a', 1], ['b', 2]]); console.log(map.size); // 2 ``` The difference is not only convenience: `Object.keys()` builds an intermediate array, while `size` is just reading a counter. **Iterability.** | Feature | `Object` | `Map` | | --- | --- | --- | | Iterated directly | No | Yes | ```javascript const map = new Map([['x', 10], ['y', 20]]); for (const [key, value] of map) { console.log(key, value); } // x 10 // y 20 ``` For an object you have to call `Object.keys()`, `Object.entries()` and similar methods. ### Performance and prototype | Feature | `Object` | `Map` | | --- | --- | --- | | Frequent inserts and deletes | Slower | Faster | | Iterating over elements | Awkward | Convenient with `for...of` | A `Map` is optimized exactly for frequent additions, deletions and traversal, whereas engines optimize objects for a stable "shape" with a known set of fields. | Feature | `Object` | `Map` | | --- | --- | --- | | Inherits from `Object.prototype` | Yes | No | | Can clash with methods (`toString`, `hasOwnProperty`) | Yes | No | A `Map` carries no "junk" in the form of built in methods, so any key is safe to use. In an object a key such as `"hasOwnProperty"` or `"__proto__"` can break your checks. ### Converting between them ```javascript const obj = { a: 1, b: 2 }; const map = new Map(Object.entries(obj)); console.log(map); // Map(2) { 'a' => 1, 'b' => 2 } const backToObj = Object.fromEntries(map); console.log(backToObj); // { a: 1, b: 2 } ``` `Object.entries()` and `Object.fromEntries()` make conversion in both directions easy. This is also how you serialize a `Map`, since `JSON.stringify(map)` on its own yields `{}`. ### What to use and when | Use | When | | --- | --- | | `Object` | a data structure with fixed properties (a user model, for instance) | | `Map` | dynamic keys, keys of any type, caches, frequent add and delete operations | **In short:** | Feature | `Object` | `Map` | | --- | --- | --- | | Key types | string or symbol | any type | | Key order | partly ordered | preserved | | Size | counted manually | `.size` | | Iterability | via `Object.keys()` | directly (`for...of`) | | Performance | lower | higher | | Use case | static data | dynamic collections | ### Common mistakes - **Using an object as a key of a plain object.** The key silently becomes the string `"[object Object]"` and all objects collapse into a single entry. - **Relying on the order of numeric object keys.** Integer like keys are always sorted ascending, regardless of insertion order. - **Writing `map.length` or `map['key']`.** The first is `undefined`, the second creates a property outside the collection; the correct forms are `map.size` and `map.get('key')`. - **Serializing a `Map` directly.** `JSON.stringify(map)` returns `{}`, you need `Object.fromEntries(map)` or an array from `[...map]` first. - **Reaching for a `Map` everywhere "because it is faster".** For a small fixed model an object is more convenient: destructuring, shorthand syntax, native JSON support. - **Forgetting that a `Map` holds keys strongly.** Object keys will not leave memory while the `Map` itself is alive; for weak references there is `WeakMap`.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.