Objeto `Map`
Este artículo explica el objeto Map.
Explicaremos paso a paso, desde operaciones básicas hasta ejemplos prácticos que son útiles en escenarios del mundo real.
YouTube Video
Objeto Map
Map es una colección que almacena pares clave-valor. Es similar a un objeto, pero se diferencia en que cualquier tipo, como objetos, funciones o tipos primitivos, puede usarse como clave y se preserva el orden de inserción.
Conceptos básicos de Map
Primero, veamos cómo crear un Map y realizar operaciones básicas.
El siguiente código es un ejemplo mínimo que crea un mapa vacío, agrega claves y recupera valores.
1// Create an empty Map and add key-value pairs
2const m = new Map();
3m.set('a', 1);
4m.set('b', 2);
5
6console.log(m.get('a')); // 1
7console.log(m.size); // 2
- En este código, puedes agregar elementos con
set, recuperar valores congety verificar la cantidad de elementos consize. Mapmantiene el orden de inserción, lo que lo hace adecuado para procesos que dependen del orden.
Comportamiento de set, get, has y delete
Aquí hay ejemplos de operaciones típicas de lectura, escritura, verificación de existencia y eliminación.
Con el siguiente código, puedes verificar los valores de retorno y efectos de cada método.
1// Demonstrate set, get, has, and delete
2const m2 = new Map();
3m2.set('x', 10);
4console.log(m2.has('x')); // true
5console.log(m2.get('y')); // undefined
6
7m2.delete('x');
8console.log(m2.has('x')); // false
9
10// set returns the map itself, allowing method chaining
11m2.set('a', 1).set('b', 2);
12console.log(m2); // Map { 'a' => 1, 'b' => 2 }
getdevuelveundefinedsi la clave no existe.hasverifica la existencia de una clave ydeleteelimina una clave.- Además, como
setdevuelve el propio Map, es posible encadenar métodos.
Cualquier tipo puede utilizarse como clave (usando objetos como claves)
Una de las principales ventajas de Map es que puedes usar objetos directamente como claves.
El siguiente ejemplo muestra cómo asociar valores en un Map usando objetos como claves.
1// Use objects as keys in a Map
2const keyObj = { id: 1 };
3const keyFunc = () => {};
4const objMap = new Map();
5
6// Another object with the same content but a different reference
7const anotherKeyObj = { id: 1 };
8
9objMap.set(keyObj, 'objectValue');
10objMap.set(keyFunc, 'functionValue');
11objMap.set(anotherKeyObj, 'anotherValue');
12
13console.log(objMap.get(keyObj)); // 'objectValue'
14console.log(objMap.get(keyFunc)); // 'functionValue'
15console.log(objMap.get(anotherKeyObj)); // 'anotherValue'
- Al usar objetos como claves, es importante que sean la misma referencia. Incluso si su contenido es el mismo, los objetos con diferentes referencias se tratan como distintos y no como la misma clave.
Iteración (bucles)
Map preserva el orden de inserción, por lo que la iteración se usa frecuentemente.
A continuación, mostramos cómo usar for...of, forEach y los métodos keys(), values() y entries().
1// Iterating a Map with for...of and forEach
2const iterMap = new Map([['a', 1], ['b', 2], ['c', 3]]);
3
4// for...of over entries (default)
5for (const [key, value] of iterMap) {
6 console.log(key, value);
7}
8
9// forEach callback
10iterMap.forEach((value, key) => {
11 console.log(key, value);
12});
13
14// keys() and values()
15console.log([...iterMap.keys()]); // ['a','b','c']
16console.log([...iterMap.values()]); // [1,2,3]
entries()devuelve un array de pares[clave, valor], que puede convertirse en un array usando la sintaxis spread. Ten en cuenta que el callback deforEachrecibe los argumentos en el ordenvalor, clave.
Convertir entre Map y Object
Puedes convertir un objeto existente a un Map, o convertir un Map a un objeto simple o a un array.
1// Convert between Map and Object / Array
2const obj = { a: 1, b: 2 };
3const mapFromObj = new Map(Object.entries(obj)); // Object -> Map
4console.log(mapFromObj.get('a')); // 1
5
6const objFromMap = Object.fromEntries(mapFromObj); // Map -> Object
7console.log(objFromMap); // { a: 1, b: 2 }
8
9const arrayFromMap = [...mapFromObj]; // Map -> Array of [key, value]
10console.log(arrayFromMap); // [['a',1], ['b',2]]
- El uso de
Object.entriesyObject.fromEntrieshace que la conversión sea fácil. Sin embargo, dado que las claves de los objetos están limitadas a cadenas o símbolos, las claves que no sean cadenas se pierden al convertir de nuevo a un objeto.
Patrón práctico: Contar frecuencias (Count Map)
Al contar la frecuencia de elementos en un array, usar un Map hace que el proceso sea más sencillo.
El siguiente código es un ejemplo de cómo usar un Map para contar la frecuencia de cadenas en un array y ordenarlas.
1// Count frequencies with Map
2const arr = ['apple','banana','apple','orange','banana','apple'];
3const freq = new Map();
4
5for (const item of arr) {
6 freq.set(item, (freq.get(item) || 0) + 1);
7}
8
9console.log([...freq.entries()]); // [['apple',3], ['banana',2], ['orange',1]]
- Usar un
Mappermite comprobar la existencia y realizar actualizaciones fácilmente. Esto también se puede hacer con objetos, peroMappuede ser más intuitivo cuando se trabaja con claves arbitrarias.
Notas sobre Map y JSON.stringify (Serialización)
JSON.stringify no puede serializar un Map directamente. Si necesitas guardar un Map, primero debes convertirlo.
El siguiente ejemplo muestra cómo convertir un Map a un array antes de pasarlo a JSON, y cómo restaurarlo.
1// Serialize and deserialize a Map
2const m3 = new Map([['x', 1], ['y', 2]]);
3const json = JSON.stringify([...m3]); // convert to array first
4console.log(json); // '[["x",1],["y",2]]'
5
6const restored = new Map(JSON.parse(json));
7console.log(restored.get('x')); // 1
- Los Maps que deban guardarse o transmitirse deben convertirse en arrays antes de serializarlos. Al restaurar, utiliza
JSON.parsepara convertirlo en un array y luego reconvertirlo en un Map.
Introducción a WeakMap y cómo usarlo
WeakMap se diferencia en que sus claves son referencias débiles (sujetas a recolección de basura).
Es útil para mantener cachés o metadatos con objetos como claves, liberándolos automáticamente cuando el objeto clave es recolectado.
1// WeakMap for metadata tied to object lifecycle
2const wm = new WeakMap();
3let obj = {};
4wm.set(obj, { meta: 'info' });
5console.log(wm.get(obj)); // { meta: 'info' }
6
7obj = null; // now the object can be GC'd and its entry removed from WeakMap
WeakMapno puede ser enumerado ni permite conocer su tamaño, pero es útil para prevenir fugas de memoria.
Resumen
Map es una colección conveniente que, a diferencia de los objetos, permite cualquier tipo de clave y preserva el orden de inserción. Al comprender todo, desde operaciones básicas hasta usos avanzados, puedes gestionar los datos de manera más flexible e intuitiva. Al usar Object y Map apropiadamente según el caso de uso, puedes mejorar enormemente la claridad y legibilidad del código.
Puedes seguir el artículo anterior utilizando Visual Studio Code en nuestro canal de YouTube. Por favor, también revisa nuestro canal de YouTube.