DEV Community

Adam Golan
Adam Golan

Posted on

Why You Should Prefer Map over Object in JavaScript

JavaScript developers often use plain objects as key-value stores, but the Mapdata structure offers several compelling advantages. Let's explore why you might want to choose Mapover a dynamic object in your next project.

1. Key Types Flexibility

One of the most significant advantages of Mapis its ability to use any value as a key, not just strings and symbols.

// With Objects, keys are always converted to strings
const obj = {};
obj[true] = "value1";
obj[1] = "value2";
obj[{ key: 1 }] = "value3";

console.log(Object.keys(obj));
// Output: ["true", "1", "[object Object]"]

// With Map, keys maintain their type
const map = new Map();
map.set(true, "value1");
map.set(1, "value2");
map.set({ key: 1 }, "value3");

console.log([...map.keys()]);
// Output: [true, 1, { key: 1 }]
Enter fullscreen mode Exit fullscreen mode

2. Size Management

Maps provide a built-in size property, while objects require manual calculation.

// With Objects
const obj = { a: 1, b: 2, c: 3 };
const size = Object.keys(obj).length; // Requires conversion to array
console.log(size); // 3

// With Map
const map = new Map([
  ['a', 1],
  ['b', 2],
  ['c', 3]
]);
console.log(map.size); // 3, direct access
Enter fullscreen mode Exit fullscreen mode

3. Better Iteration Performance

Maps are designed for frequent additions and removals of key-value pairs, with better performance for iteration.

// Performance test
const iterations = 1000000;

// Object
const obj = {};
console.time('Object');
for (let i = 0; i < iterations; i++) {
  obj[`key${i}`] = i;
}
for (const key in obj) {
  const value = obj[key];
}
console.timeEnd('Object');

// Map
const map = new Map();
console.time('Map');
for (let i = 0; i < iterations; i++) {
  map.set(`key${i}`, i);
}
for (const [key, value] of map) {
  // Direct value access
}
console.timeEnd('Map');
Enter fullscreen mode Exit fullscreen mode

4. Clear Methods for Common Operations

Map provides clear, purpose-built methods for common operations.

// Map operations
const map = new Map();

// Adding entries
map.set('key1', 'value1');
map.set('key2', 'value2');

// Checking existence
console.log(map.has('key1')); // true

// Getting values
console.log(map.get('key1')); // 'value1'

// Deleting entries
map.delete('key1');

// Clearing all entries
map.clear();

// Compare with Object
const obj = {};

// Adding entries
obj.key1 = 'value1';
obj['key2'] = 'value2';

// Checking existence
console.log('key1' in obj); // true
// or
console.log(obj.hasOwnProperty('key1')); // true

// Getting values
console.log(obj.key1); // 'value1'

// Deleting entries
delete obj.key1;

// Clearing all entries
for (const key in obj) {
  delete obj[key];
}
Enter fullscreen mode Exit fullscreen mode

5. No Prototype Chain Issues

Maps don't have inheritance issues that can plague objects.

const obj = {};
console.log(obj.toString); // [Function: toString]
console.log(obj.hasOwnProperty('toString')); // false

const map = new Map();
console.log(map.get('toString')); // undefined
console.log(map.has('toString')); // false
Enter fullscreen mode Exit fullscreen mode

6. Easy Iteration with Multiple Methods

Maps offer various built-in iteration methods.

const map = new Map([
  ['name', 'John'],
  ['age', 30],
  ['city', 'New York']
]);

// Iterate over entries
for (const [key, value] of map) {
  console.log(`${key}: ${value}`);
}

// Iterate over keys
for (const key of map.keys()) {
  console.log(key);
}

// Iterate over values
for (const value of map.values()) {
  console.log(value);
}

// Using forEach
map.forEach((value, key) => {
  console.log(`${key}: ${value}`);
});
Enter fullscreen mode Exit fullscreen mode

When to Still Use Objects

While Maps are powerful, objects are still preferable in certain scenarios:

  1. When you need JSON serialization (Maps aren't automatically serializable)
  2. When working with simple property access
  3. When you need to use object spread operator
  4. When dealing with JSON APIs
// JSON serialization
const obj = { name: 'John', age: 30 };
const jsonStr = JSON.stringify(obj); // Works fine

const map = new Map([['name', 'John'], ['age', 30]]);
const jsonStr2 = JSON.stringify(map); // Results in '{}'

// However, you can convert Map to Object for serialization
const mapAsObj = Object.fromEntries(map);
const jsonStr3 = JSON.stringify(mapAsObj); // Works fine
Enter fullscreen mode Exit fullscreen mode

Conclusion

Maps are the better choice when you need:

  • Non-string keys
  • Frequent additions and removals
  • Easy size tracking
  • Better iteration performance
  • Clear and consistent methods for common operations
  • Freedom from prototype chain concerns

Consider your use case carefully, but don't be afraid to reach for Mapwhen these benefits align with your needs.

Top comments (2)

Collapse
 
lico profile image
SeongKuk Han

As we can assume by their names, json is a Javascipt Object Notation and map is a map we know. We can use a JSON object as a JSON object as it is. However, we have to convert from json to map if we want to json as a map. There is one more step to use them from json. As we use JSON, we can reduce an uncessary process, especially, where converting between json and map hapeen frequently. I think that's maybe why people use just json itself but I agree that map is clear to use when we that as a map, because map is map. I'm not sure what I'm saying sounds make sense tho 😂

Collapse
 
wizard798 profile image
Wizard

Which is good for higher rate of data, suppose 1Million entries,
As both will use most size of memory

And isn't map performance affected by size of data, cause when map will be full it'll make new map of more size, then copy all elements in that map?