Pregunta 1Con const ids = new Set(["u-1", "u-2"]);, ejecuta ids.add("u-1");. ¿Cuál es ids.size?
Map y Set — eliminar duplicados y conteos con clave
Aprende Set, que guarda cada valor una sola vez, y Map, que guarda pares clave-valor en orden de registro.
Reúne en un array las etiquetas de un producto, y la misma etiqueta aparece una y otra vez — saber cuántas hay realmente distintas exige comprobar con includes cada vez. Querer guardar un par clave-valor, como un contador de stock indexado por ID de producto, choca con el mismo muro usando solo arrays: harían falta dos arrays separados para los ID y las cantidades, alineados por posición, y las claves de un objeto se limitan a cadenas y symbol, así que un número no puede usarse tal cual como clave.
Este artículo cubre Set, que nunca guarda duplicados, y Map, que puede usar algo más que cadenas como claves.
Eliminar duplicados — construir un Set
Imagina que quieres saber cuántas etiquetas distintas están realmente en uso en una lista de productos etiquetados. En un array normal, la misma etiqueta aparece más de una vez, así que contarla tal cual infla el total. Necesitas una estructura de datos que guarde los valores sin duplicados desde el principio.
Un Set (una estructura de datos que guarda cada valor solo una vez) se construye pasando un array, como en new Set(tags). El new al principio es sintaxis que pones antes de crear una instancia nueva de un tipo fijo de estructura de datos, como Set o Map.
Como el mismo valor nunca añade un duplicado, con solo leer size sabes el número de valores distintos. Si dos valores cuentan como el mismo sigue la misma regla que ===.
Un Set no es un array, así que un index como uniqueTags[0] no te devolverá nada. Cuando lo necesites como array, conviértelo con spread syntax, como en [...uniqueTags].
El orden se mantiene exactamente como se añadieron los elementos por primera vez, así que el orden de primera aparición del array original se conserva sin cambios.
const tags = ["Sale", "New", "Sale", "Free Shipping"];
// Pasa un array, y obtienes un Set sin duplicados
const uniqueTags = new Set(tags);
console.log(uniqueTags.size); // 3
// Vuelve a convertirlo en array con spread syntax (se conserva el orden de adición)
console.log([...uniqueTags].join(", ")); // Sale, New, Free Shipping
// El array original queda intacto
console.log(tags.length); // 4
// También puedes empezar desde un Set vacío
const empty = new Set();
console.log(empty.size); // 0
Añadir y eliminar valores — add, has y delete
A veces quieres registrar IDs de visitantes y contar a la misma persona como 1 sin importar cuántas veces vuelva. Guarda esto en un array, y cada adición significa comprobar con includes antes de push — cuantos más registros se acumulan, más tarda esa comprobación.
Un Set tiene add para añadir un valor, has para comprobar si tiene uno, delete para eliminar uno, y size para el conteo. add no hace nada cuando llega el mismo valor, así que nunca necesitas comprobar antes de añadir.
has devuelve true o false, y delete devuelve si realmente eliminó algo.
addir el mismo valor cualquier número de veces nunca aumenta el conteo. Solo eliminar lo reduce.const visitors = new Set(["u-102", "u-337"]);
// Comprueba si lo tiene
console.log(visitors.has("u-102")); // true
console.log(visitors.has("u-999")); // false
// Añade uno. El mismo valor no cambia el conteo
visitors.add("u-541");
console.log(visitors.size); // 3
visitors.add("u-541");
console.log(visitors.size); // 3
// Elimina uno. Vuelve si realmente eliminó algo
console.log(visitors.delete("u-102")); // true
console.log(visitors.delete("u-102")); // false (ya se había ido)
console.log(visitors.size); // 2
Guardar pares clave-valor — Map
A veces quieres guardar una clave y un valor como par, como un contador de stock por ID de producto. Un objeto también puede hacerlo, pero para contar claves que se deciden en tiempo de ejecución —como IDs— y ajustarlas con el tiempo, una estructura de datos con métodos dedicados es más adecuada.
Un Map (una estructura de datos que guarda pares clave-valor en el orden en que se registraron) se construye con new Map(), y registras entradas con set(key, value). Para leer una, usa get(key); para comprobar si existe, has(key); para el conteo, size.
Haz set sobre la misma clave otra vez, y el valor se sobrescribe. Para empezar con entradas ya rellenadas, pásale un array de pares, como en new Map([["P-001", 12], ["P-002", 5]]).
set registra un par, y get busca un valor por clave. Una clave sin entrada devuelve undefined.const stock = new Map();
// Registra un par con set
stock.set("P-001", 12);
stock.set("P-002", 5);
console.log(stock.size); // 2
// Busca un valor por su clave con get
console.log(stock.get("P-002")); // 5
console.log(stock.get("P-999")); // undefined
console.log(stock.has("P-999")); // false
// Haz set sobre la misma clave otra vez, y sobrescribe
stock.set("P-001", 8);
console.log(stock.get("P-001")); // 8
console.log(stock.size); // 2 (el conteo no crece)
// También lo puedes construir con pares ya rellenados
const prices = new Map([["P-001", 3980], ["P-002", 2480]]);
console.log(prices.get("P-001")); // 3980
Los valores de un Map no se pueden leer con notación de punto
Escribe stock["P-001"] en vez de stock.get("P-001"), y no obtendrás el valor de vuelta. Esa sintaxis busca una propiedad en el propio objeto Map, que no tiene nada que ver con los pares que registraste, así que devuelve undefined. Pasa la lectura y escritura por get y set.
Elegir entre Map y Object — tipo de clave y orden
Como guarda claves y valores igual que un objeto, eliges entre ellos. Cuando las claves están fijas en el momento en que escribes el código, como campos de configuración, un objeto funciona; cuando estás contando claves que crecen en tiempo de ejecución, como IDs o fechas, Map es más fácil de manejar.
El tipo de clave y el orden son en lo que basas esa decisión.
Las claves de un objeto se convierten a cadenas, así que incluso escribiendo record[2026], la clave real es "2026". Un Map usa el valor que le pases como clave exactamente tal cual, así que el número 2026 y la cadena "2026" se tratan como claves distintas.
El orden también funciona distinto — un Map siempre conserva el orden en que se registraron las cosas.
| Aspecto | Object | Map |
|---|---|---|
| Tipos permitidos como clave | Se convierten a cadenas | Cualquier tipo, tal cual |
| Orden | Las claves tipo entero se ordenan primero | Se mantiene el orden de registro |
| Contar entradas | length de Object.keys | size |
| Leer y escribir | obj.key / obj[key] | get y set |
| Mejor para | Una colección fija de campos | Contar claves que crecen en tiempo de ejecución |
Para listar el contenido de un Map, escribe [...stock.entries()] para convertirlo en un array de pares [clave, valor], cada uno un array de 2 elementos. Eso te deja sacar un par a la vez, como en entries[0]. Repetir el mismo paso una vez por cada par, sean los que sean, se cubre de nuevo en el artículo de bucles.
Cuando solo necesites las claves, usa stock.keys() — pero como lo que devuelve no es un array, no puedes encadenar join directamente sobre eso. Escribe [...stock.keys()] para convertirlo antes a array.
const scores = new Map([["math", 80]]);
// Un Map conserva una clave numérica como número
scores.set(2026, "this year's tally");
console.log(scores.get(2026)); // this year's tally
console.log(scores.get("2026")); // undefined (una clave distinta)
// Las claves de un objeto se convierten a cadenas
const record = {};
record[2026] = "this year's tally";
console.log(Object.keys(record)[0]); // 2026
console.log(typeof Object.keys(record)[0]); // string
console.log(record["2026"]); // this year's tally (se trata como la misma clave)
// Convierte keys() / entries() a array con spread syntax antes de usarlos
console.log([...scores.keys()].join(", ")); // math, 2026
const pairs = [...scores.entries()];
console.log(pairs[0].join(": ")); // math: 80
// Un objeto ordena primero las claves de tipo entero
const ranking = {};
ranking[3] = "c";
ranking[1] = "a";
console.log(Object.keys(ranking).join(", ")); // 1, 3
Verificación de conocimientos
Responde cada pregunta una a una.
Pregunta 2Con stock como Map, ¿qué devuelve stock.get("P-999") para una clave no registrada?
Pregunta 3Registra el número 2026 como clave. ¿Qué diferencia hay entre Map y un objeto?