DMarlon Studio

Lección 8 · 8 de 20

Map, Set y WeakMap · JavaScript

Agrupe y cuente datos en JavaScript con Map y Set, y asocie información a objetos sin modificarlos con WeakMap, usando pedidos reales.

JavaScript · Map, Set y WeakMap en DMarlon Studio: el código del ejemplo y su salida en la terminal

Un `Set` guarda valores sin repetir. Al crearlo con los productos de los pedidos, Mouse aparece una sola vez aunque se haya vendido dos veces. size dice cuántos hay y has() comprueba si existe uno, mucho más rápido que buscar en un array. [...products] lo convierte de nuevo en array.

Un `Map` es un diccionario de clave y valor con ventajas sobre un objeto normal: las claves pueden ser de cualquier tipo, conserva el orden de inserción y se recorre directamente con for...of, que entrega pares [clave, valor]. El ejemplo agrupa los pedidos por cliente con get() y set(); ?? [] da una lista vacía la primera vez que aparece un cliente.

Con objetos como clave, Map compara por identidad, no por contenido: orders[0] encuentra su estado, pero una copia con los mismos datos ({ ...orders[0] }) es otro objeto y devuelve undefined.

Un `WeakMap` solo admite objetos como clave y no impide que el recolector de basura los elimine cuando nadie más los usa. Es ideal para asociar datos a un objeto sin tocarlo: visits cuenta las visitas de ana, pero ana no recibe ninguna propiedad nueva ("visits" in ana es false). A cambio, un WeakMap no se puede recorrer ni tiene size.

Código · main.js

const orders = [  { id: 1, customer: "Ana", product: "Laptop" },  { id: 2, customer: "Luis", product: "Mouse" },  { id: 3, customer: "Ana", product: "Mouse" },  { id: 4, customer: "Marta", product: "Keyboard" },];// Set: a collection of unique values.const products = new Set(orders.map((o) => o.product));console.log("Products:", [...products].join(", "), `(${products.size})`);console.log("Do we sell monitors?", products.has("Monitor"));// Map: keys of any type, kept in insertion order.const byCustomer = new Map();for (const o of orders) {  const ids = byCustomer.get(o.customer) ?? [];  byCustomer.set(o.customer, [...ids, o.id]);}for (const [customer, ids] of byCustomer) console.log(customer, "->", ids.join(", "));// Objects as keys: a Map compares them by identity, not by content.const status = new Map([[orders[0], "shipped"]]);console.log("Order 1:", status.get(orders[0]), "| copy:", status.get({ ...orders[0] }));// WeakMap: extra data per object that does not keep the object alive.const visits = new WeakMap();function visit(user) {  visits.set(user, (visits.get(user) ?? 0) + 1);  return visits.get(user);}const ana = { name: "Ana" };visit(ana);visit(ana);console.log(ana.name, "visits:", visit(ana), "| stored on the object?", "visits" in ana);

Salida · node main.js

Products: Laptop, Mouse, Keyboard (3)
Do we sell monitors? false
Ana -> 1, 3
Luis -> 2
Marta -> 4
Order 1: shipped | copy: undefined
Ana visits: 3 | stored on the object? false

Para recordar

  • Set guarda valores únicos y responde rápido a has().
  • Map admite claves de cualquier tipo y mantiene el orden de inserción.
  • Las claves que son objetos se comparan por identidad.
  • WeakMap asocia datos a objetos sin impedir que se liberen.

Ejercicio

Cree un Map que cuente cuántos pedidos tiene cada producto (Mouse -> 2) y escríbalo ordenado de mayor a menor con [...map].sort(...).