Qué es el objeto Map que nos permite guardar colecciones de clave / valor. Para qué lo podemos usar en Javascript, con ejemplos prácticos.
En este artículo vamos a ver el objeto Map, que nos permite crear diccionarios en Javascript, es decir, estructuras de datos con una colección de elementos clave / valor. Es un objeto que se soporta en todos los navegadores actualmente, por lo que podéis usar con toda tranquilidad. No obstante, apareció un poco más recientemente y de hecho está reflejada en especificaciones recientes de ECMAScript.
No debes de confundir el objeto Map con el método map() de los arrays, que es una cosa distinta, ni con objetos JSON que también albergan pares clave / valor.
Map en JavaScript
Map es una colección de pares clave-valor, parecida a un objeto Javascript de toda la vida, pero con diferencias importantes que resultan bastante interesantes y nos permiten disfrutar utilidades diversas.
La diferencia más notable en lo que respecta a la estructura de datos es que con Map podemos trabajar con claves de cualquier tipo, no solamente una cadena, por lo que nos ofrece muchas posibilidades de indexación. Además mantiene el orden de inserción y ofrece métodos pensados específicamente para gestionar datos asociados. Pero donde realmente encontramos la potencia de este objeto es en la cantidad de métodos que nos ofrece para acceder a los elementos del diccionario y hacer búsquedas directas.
Es una estructura muy útil cuando necesitas relacionar identificadores con valores de forma clara y sencilla, consiguiendo a la vez algunas utilidades extra para trabajar con la estructura de datos.
Para usar un objeto map tenemos primero que instanciarlo.
const mapa = new Map();
A partir de ahí podrás usar diversas utilidades que nos ofrece este objeto a través de sus métodos. Por ejemplo puedes insertar valores, recuperarlos y muchas otras cosas, como vamos a ver en este artículo.
Map vs objetos Javascript
Un Map almacena elementos como pares clave / valor, igual que los objetos tradicionales. Sin embargo, a diferencia de un objeto normal, las claves no necesitan ser siempre cadenas: pueden ser números, objetos, funciones o cualquier otro valor. Eso lo convierte en una herramienta más flexible que los objetos de toda la vida.
const mapa = new Map();
mapa.set('nombre', 'Ana');
mapa.set(10, 'diez');
mapa.set(true, 'verdadero');
Otro ejemplo un poco más avanzado y rebuscado sería trabajar con claves de tipo objeto, pero literalmente podemos usar cualquier cosa para las claves, por ejemplo una función.
const usuario1 = { id: 1 };
const usuario2 = { id: 2 };
const edades = new Map();
edades.set(usuario1, 28);
edades.set(usuario2, 34);
console.log(edades.get(usuario1)); // 28
De todos modos, lo típico es usarlo con cadenas, como ves en el siguiente ejemplo:
const edadUsuarios = new Map();
edadUsuarios.set('ana', 28);
edadUsuarios.set('luis', 34);
Luego podemos acceder a los valores insertados con el método get() y podemos saber si existe una llave en concreto con el método has().
console.log(edadUsuarios.get('ana')); // 28
console.log(edadUsuarios.has('luis')); // true
Otras diferencias destacadas es que Map puede funcionar como diccionario, pero además:
- Las claves pueden ser de cualquier tipo.
- Tiene métodos dedicados como
set(),get(),has(),delete()yclear(). - Su tamaño se consulta con
size. - Iterar sobre sus elementos es más natural.
En cambio, un objeto está más ligado al uso de propiedades y carece de las utilidades avanzadas que te ofrece Map para trabajar con las propiedades de manera dinámica.
Métodos principales de Map
Map nos ofrece una enorme cantidad de métodos y puedes consultarlos todos en la ayuda de Map Object de Mozilla para desarrolladores.
Los métodos más usados de Map que sí o sí debes conocer son:
set(clave, valor): añade o actualiza un elemento.get(clave): obtiene el valor asociado.has(clave): comprueba si existe la clave.delete(clave): elimina una entrada.clear(): borra todo.size: devuelve el número de elementos.
Ejemplo:
const mapa = new Map();
mapa.set('nombre', 'Miguel');
mapa.set('pais', 'España');
console.log(mapa.get('nombre')); // Miguel
console.log(mapa.has('pais')); // true
console.log(mapa.size); // 2
mapa.delete('pais');
console.log(mapa.size); // 1
Iteración sobre Map
Una de las prácticas frecuentes que necesitarás hacer con Map es recorrerlo de forma natural. Como mantiene el orden de inserción, al iterarlo obtendrás primero los elementos que se añadieron antes y después los más recientes. Esto lo hace muy cómodo cuando quieres procesar datos asociados sin perder el orden original.
La forma más habitual de recorrer un Map es con for...of:
const mapa = new Map([
['nombre', 'Ana'],
['edad', 28],
['pais', 'España']
]);
for (const [clave, valor] of mapa) {
console.log(clave, valor);
}
En este caso, cada elemento del Map se obtiene como un par [clave, valor]. Esa desestructuración es muy útil porque permite trabajar con ambos valores de manera directa.
También puedes recorrer solo las claves, solo los valores o ambas cosas:
for (const clave of mapa.keys()) {
console.log(clave);
}
for (const valor of mapa.values()) {
console.log(valor);
}
for (const entrada of mapa.entries()) {
console.log(entrada);
}
En realidad, mapa.entries() devuelve pares [clave, valor], y es el comportamiento que usa el propio Map cuando lo recorres directamente con for...of.
Si necesitas ejecutar una acción para cada entrada, también puedes usar forEach que se parece al método que conoces de los arrays:
mapa.forEach((valor, clave) => {
console.log(clave, valor);
});
Hay un detalle interesante de
forEachque es el orden de los parámetros:valor, clave, noclave, valor, que es justo al revés de `for...of. Ese cambio de orden es una fuente frecuente de confusión.
Conversión entre Map y objeto/array
Algo que a veces necesitarás es convertir Mapa un objeto. Esto es perfectamente posible, así como convertirlo a otras estructuras como un array. Vamos a ver algunos ejemplos directamente, ya que es muy sencillo.
De Map a array
La conversión más sencilla es a array de pares:
const mapa = new Map([
['nombre', 'Ana'],
['edad', 28]
]);
const array = Array.from(mapa);
console.log(array);
// [['nombre', 'Ana'], ['edad', 28]]
También puedes usar el spread operator de Javascript, como puedes ver a continuación:
const array = [...mapa];
Ambas opciones producen un array de entradas, donde cada elemento es un par [clave, valor].
De array a Map
El paso contrario es también muy sencillo, solo que necesitarías un array de arrays para poder definir las cadenas de índice y sus valores.
const datos = [
['nombre', 'Luis'],
['edad', 34]
];
const mapa = new Map(datos);
Esto es muy útil cuando los datos llegan en formato estructurado y quieres aprovechar las ventajas de Map.
De Map a objeto
Si las claves son cadenas, puedes convertir un Map a objeto con Object.fromEntries:
const mapa = new Map([
['nombre', 'Marta'],
['edad', 22]
]);
const objeto = Object.fromEntries(mapa);
console.log(objeto);
// { nombre: 'Marta', edad: 22 }
Esta conversión es práctica si necesitas trabajar con una estructura más tradicional o preparar datos para JSON.
De objeto a Map
También puedes hacer el camino inverso con Object.entries:
const objeto = {
nombre: 'Carlos',
edad: 31
};
const mapa = new Map(Object.entries(objeto));
Esto convierte las propiedades del objeto en pares [clave, valor] y luego los pasa al constructor de Map.
Para qué sirve Map
Map sirve para asociar datos de forma explícita. Es especialmente útil cuando:
- Necesitas claves que no sean solo cadenas.
- Quieres conservar el orden en que se insertaron los elementos.
- Vas a hacer muchas búsquedas por clave.
- Quieres una API más clara que la de un objeto para almacenar relaciones.
Un caso típico es guardar datos de configuración, cachés, contadores o correspondencias entre objetos y valores.
Uso de Map en librerías y frameworks Javascript
Además de los casos de uso prácticos que hemos comentado en este artículo, también vas a encontrar usos del objeto Map cuando trabajes con librerías modernas de JavaScript.
Por ejemplo, muchas librerías de UI o de utilidad usan Map para guardar datos temporales relacionados con nodos, instancias o referencias. Esto resulta especialmente útil cuando la clave es un objeto del DOM o una instancia de clase, porque Map puede usar objetos como claves sin convertirlos en cadenas.
Un ejemplo típico donde usamos Map, por ver algo concreto, es en la librería Lit, para el desarrollo con Web Components estándar de Javascript, cuando implementamos el método del ciclo de vida updated().
El método updated(changedProperties) de los componentes Lit recibe un Map con las propiedades que han cambiado durante esa actualización. Las claves son los nombres de las propiedades y los valores son sus valores anteriores (que tenían antes de la actualización). Gracias a este método podemos hacer comportamientos detallados cuando cambia el estado de los componentes.
Un ejemplo básico podría ser así:
updated(changedProperties) {
if (changedProperties.has('titulo')) {
console.log('El título cambió');
}
}
O incluso recuperar el valor anterior:
updated(changedProperties) {
const anterior = changedProperties.get('titulo');
if (anterior !== undefined) {
console.log('Valor anterior:', anterior);
}
}
Espero que este ejemplo de Map te ayude a ver un poquito mejor la utilidad de este objeto de Javascript, que aquí es ideal porque nos permite saber con una API muy potente qué propiedades han cambiado y acceder a sus valores anteriores.
Miguel Angel Alvarez
Fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Com...