Map vs plain object: keys can be any type, maintains insertion order, has .size, is directly iterable, better performance for frequent add/delete.
Set vs array: values must be unique, has O(1) lookup with .has(), no index access.
// Map
const map = new Map();
map.set('string', 1);
map.set(42, 'number key'); // any type as key!
map.set({}, 'object key');
map.get('string'); // 1
map.has(42); // true
map.size; // 3
map.delete(42);
// Iterate
for (const [k, v] of map) console.log(k, v);
[...map.keys()]; [...map.values()]; [...map.entries()];
// Convert to/from object
const obj = Object.fromEntries(map);
new Map(Object.entries(obj));
// Set
const set = new Set([1, 2, 2, 3, 3]); // {1, 2, 3} — duplicates removed
set.add(4);
set.has(2); // true — O(1)
set.size; // 4
// Remove duplicates from array (classic use)
const unique = [...new Set([1,2,2,3,3,3])]; // [1, 2, 3]
// Set operations
const a = new Set([1, 2, 3]);
const b = new Set([2, 3, 4]);
const union = new Set([...a, ...b]); // {1,2,3,4}
const intersection = new Set([...a].filter(x => b.has(x))); // {2,3}
💡 Use Map over objects when keys are non-strings, when insertion order matters, or when keys are frequently added/removed. Use Set for unique-value tracking.