¿Cuál es la Diferencia Entre Map, Set y Object en JavaScript?
Estás refactorizando un componente y necesitas almacenar pares clave-valor. Por costumbre, recurres a un objeto, pero te detienes. ¿Debería ser un Map? ¿Funcionaría mejor un Set aquí? Esta decisión importa más de lo que parece: cada estructura tiene características de rendimiento y significado semántico distintos que afectan la claridad y eficiencia de tu código.
Esta comparación de estructuras de datos de JavaScript desglosa las diferencias prácticas entre Map, Set y Object para que puedas tomar la decisión correcta en código de producción.
Puntos Clave
- Los Objects convierten las claves a strings, mientras que los Maps preservan los tipos de clave exactamente—esta distinción previene errores sutiles de colisión.
- Los Maps superan a los Objects en adiciones y eliminaciones frecuentes, mientras que los Objects sobresalen en cargas de trabajo con muchas lecturas y estructuras estables.
- Los Sets proporcionan verificaciones de pertenencia O(1) y ahora incluyen métodos nativos
union,intersectionydifferenceen JavaScript moderno. - Por defecto, usa Objects para datos estructurados, recurre a Maps cuando las claves son dinámicas o no son strings, y usa Sets cuando la unicidad es tu preocupación principal.
Propósito Principal: Cuándo Usar Map vs Set vs Object
La diferencia entre Map y Object en JavaScript se reduce a la intención y el manejo de claves:
- Object: Datos estructurados con claves string/symbol conocidas. Piensa en configuración, props de componentes, respuestas de API.
- Map: Colecciones dinámicas clave-valor donde las claves pueden ser de cualquier tipo. Piensa en cachés, tablas de búsqueda con claves de objeto, adiciones y eliminaciones frecuentes.
- Set: Colecciones de valores únicos sin claves. Piensa en deduplicación, seguimiento de elementos vistos, verificaciones de pertenencia.
Manejo de Claves: La Diferencia Fundamental Entre Map y Object
Los Objects convierten las claves a strings. Los Maps preservan los tipos de clave exactamente.
const obj = {}
obj[1] = 'number'
obj['1'] = 'string'
console.log(Object.keys(obj)) // ['1'] — colisión
const map = new Map()
map.set(1, 'number')
map.set('1', 'string')
console.log(map.size) // 2 — claves distintas
Los Maps también aceptan objetos como claves—algo que los objects fundamentalmente no pueden hacer sin soluciones alternativas de serialización.
const userCache = new Map()
const user = { id: 42 }
userCache.set(user, { lastSeen: Date.now() })
Consulta la documentación de MDN para Map para conocer la semántica completa de las claves.
Semántica de Iteración y Ordenamiento
Las tres estructuras tienen un orden de iteración definido, pero la semántica difiere:
Map y Set: Orden de inserción puro. Siempre.
Object: Orden de inserción para claves string, pero las claves indexadas por enteros (ej., '1', '42') se ordenan numéricamente primero. Esto sorprende a los desarrolladores:
const obj = { b: 1, 2: 2, a: 3, 1: 4 }
console.log(Object.keys(obj)) // ['1', '2', 'b', 'a']
Los Maps y Sets son directamente iterables con for...of. Los Objects requieren Object.keys(), Object.values() o Object.entries().
Características de Rendimiento a Escala
Para la pregunta sobre el rendimiento de JavaScript Map vs Set vs Object, el contexto importa:
Los Objects sobresalen en cargas de trabajo con muchas lecturas y claves string. Los motores modernos como V8 optimizan el acceso a propiedades mediante clases ocultas, haciendo las lecturas muy rápidas—cuando la forma del objeto permanece estable.
Los Maps ganan en adiciones y eliminaciones frecuentes. La eliminación de propiedades de objetos (mediante delete) puede desencadenar desoptimización al invalidar las clases ocultas. La especificación ECMAScript garantiza un tiempo de acceso promedio sublineal para Maps, sin exigir una implementación interna específica.
Los Sets proporcionan verificaciones de pertenencia O(1) mediante has(), superando a includes() de arrays para cualquier tamaño de colección no trivial.
Discover how at OpenReplay.com.
Operaciones Nativas de Set
Set ahora incluye métodos integrados para operaciones comunes (consulta la documentación de MDN para Set):
const a = new Set([1, 2, 3])
const b = new Set([2, 3, 4])
a.union(b) // Set {1, 2, 3, 4}
a.intersection(b) // Set {2, 3}
a.difference(b) // Set {1}
a.symmetricDifference(b) // Set {1, 4}
a.isSubsetOf(b) // false
Estos métodos tienen amplio soporte en navegadores modernos.
Escenarios Prácticos de Frontend
Usa Object cuando:
- Definas props de componentes o configuración
- Trabajes con serialización JSON (los Maps no se serializan directamente)
- Las claves sean conocidas en tiempo de escritura
Usa Map cuando:
- Las claves sean dinámicas o proporcionadas por el usuario (evita contaminación de prototipos)
- Necesites referencias de objetos como claves
- El seguimiento de tamaño importe (
map.sizevsObject.keys(obj).length) - Construyas cachés con actualizaciones frecuentes
Usa Set cuando:
- Rastrees IDs únicos o elementos vistos
- Dedupliques arrays:
[...new Set(array)] - Necesites pruebas de pertenencia rápidas
Referencia Rápida
| Característica | Object | Map | Set |
|---|---|---|---|
| Tipos de clave | string, symbol | any | N/A (solo valores) |
| Tamaño | Object.keys().length | .size | .size |
| Iteración | indirecta | directa | directa |
| Soporte JSON | nativo | manual | manual |
| Riesgo de prototipo | sí | no | no |
Conclusión
La elección entre Map, Set y Object no se trata de cuál es “mejor”—se trata de hacer coincidir la estructura de datos con tu caso de uso. Los Objects siguen siendo la elección correcta para datos estructurados con claves string. Los Maps manejan escenarios dinámicos clave-valor de manera limpia. Los Sets resuelven problemas de unicidad eficientemente.
Por defecto, usa objects por simplicidad. Recurre a Map cuando necesites sus capacidades específicas. Usa Set cuando la unicidad sea tu preocupación principal.
Preguntas Frecuentes
No directamente. JSON.stringify no maneja Maps de forma nativa. Necesitas convertir el Map a un array de entradas primero usando Array.from(map) o el operador spread, luego convertir ese array a string. Para restaurarlo, analiza el JSON y pasa el array resultante al constructor de Map: new Map(JSON.parse(jsonString)).
Los Maps manejan inserciones y eliminaciones frecuentes sin la desoptimización que puede causar la eliminación de propiedades de objetos. También rastrean el tamaño de forma nativa con la propiedad size, aceptan cualquier tipo de valor como clave incluyendo nodos DOM o referencias de objetos, y no conllevan riesgo de contaminación de prototipos por claves proporcionadas por el usuario.
Estos métodos ahora tienen amplio soporte en navegadores modernos. Si necesitas soportar entornos más antiguos, consulta las tablas de compatibilidad o usa un polyfill.
Usa un array cuando el orden de inserción con duplicados importe, cuando necesites acceso basado en índices, o cuando la colección sea lo suficientemente pequeña como para que la sobrecarga de un Set no esté justificada. Para colecciones más grandes donde la unicidad y las búsquedas rápidas son prioridades, un Set es la mejor opción.
Complete picture for complete understanding
Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.
Check our GitHub repo and join the thousands of developers in our community.