WeakMap y WeakSet: Colecciones con Referencias Débiles
Aprende a usar WeakMap y WeakSet para gestionar datos con recolección de basura automática. Descubre cuándo usar estas colecciones especiales en lugar de Map y Set.
TL;DR - Resumen rápido
- WeakMap y WeakSet solo aceptan objetos como claves/valores
- Las claves/valores se recolectan automáticamente cuando no hay referencias
- No son iterables y no tienen métodos como size, forEach
- Ideales para cachés y metadatos de objetos
- Ayudan a evitar fugas de memoria en aplicaciones complejas
Introducción a WeakMap y WeakSet
WeakMap y WeakSet son estructuras de datos introducidas en ES6 (ECMAScript 2015) que funcionan de manera similar a Map y Set, pero con una diferencia fundamental: solo aceptan objetos como claves o valores, y permiten la recolección de basura automática.
La característica principal de estas colecciones es que mantienen referencias débiles a los objetos. Cuando un objeto ya no tiene referencias activas en tu código, WeakMap o WeakSet eliminan automáticamente esa entrada, permitiendo que el garbage collector libere la memoria. Esto las hace ideales para cachés y metadatos que podrían causar fugas de memoria.
- Solo aceptan objetos como claves/valores
- Referencias débiles: se recolectan automáticamente
- No son iterables: no tienen size, forEach, entries()
- No se pueden iterar con for...of
- Ideales para cachés y metadatos de objetos
¿Por qué WeakMap/WeakSet y no Map/Set?
Map y Set mantienen referencias fuertes a los objetos, lo que impide que el garbage collector elimine esos objetos mientras existan en la colección. WeakMap y WeakSet usan referencias débiles, permitiendo la recolección automática cuando los objetos ya no se usan.
WeakMap Básico
WeakMap funciona como Map, pero solo acepta objetos como claves. Los métodos son similares: set(), get(), has(), delete(). La diferencia principal es el comportamiento de recolección de basura automática.
Crear y Usar WeakMap
Puedes crear un WeakMap vacío usando el constructor new WeakMap(). Los métodos funcionan de manera similar a Map, pero recuerda que las claves deben ser objetos.
WeakMap mantiene referencias débiles a los objetos usados como claves. Cuando el objeto ya no tiene referencias activas, WeakMap elimina automáticamente esa entrada, permitiendo que el garbage collector libere la memoria.
Métodos de WeakMap
WeakMap proporciona métodos similares a Map: set(), get(), has(), delete(). Sin embargo, no tiene métodos como size, forEach, entries(), keys(), values() porque no son iterables.
Los métodos de WeakMap funcionan de manera similar a Map, pero con la diferencia de que las entradas se recolectan automáticamente cuando los objetos ya no tienen referencias. Esto es útil para cachés donde quieres que los datos se limpien automáticamente.
Limitaciones de WeakMap
WeakMap no es iterable y no tiene métodos como size, forEach, entries(), keys(), values(). No puedes usar for...of ni forEach. Solo puedes acceder a valores específicos usando get() y verificar existencia con has().
WeakSet Básico
WeakSet funciona como Set, pero solo acepta objetos como valores. Los métodos son similares: add(), has(), delete(). La diferencia principal es el comportamiento de recolección de basura automática.
Crear y Usar WeakSet
Puedes crear un WeakSet vacío usando el constructor new WeakSet(). Los métodos funcionan de manera similar a Set, pero recuerda que los valores deben ser objetos.
WeakSet mantiene referencias débiles a los objetos. Cuando un objeto ya no tiene referencias activas, WeakSet elimina automáticamente esa entrada, permitiendo que el garbage collector libere la memoria.
Métodos de WeakSet
WeakSet proporciona métodos similares a Set: add(), has(), delete(). Sin embargo, no tiene métodos como size, forEach, entries(), values() porque no es iterable.
Los métodos de WeakSet funcionan de manera similar a Set, pero con la diferencia de que las entradas se recolectan automáticamente cuando los objetos ya no tienen referencias. Esto es útil para mantener registros de objetos sin causar fugas de memoria. Al igual que WeakMap, WeakSet no es iterable y no tiene métodos como size, forEach, entries(), values().
Referencias Débiles y Garbage Collection
El concepto fundamental de WeakMap y WeakSet es el de referencias débiles. Cuando un objeto ya no tiene referencias activas en tu código, el garbage collector puede recolectarlo automáticamente, y WeakMap/WeakSet eliminarán la entrada correspondiente.
Cómo Funciona el Garbage Collection
El garbage collector de JavaScript elimina objetos que ya no son accesibles desde tu código. WeakMap y WeakSet usan referencias débiles, lo que significa que no impiden que el garbage collector elimine los objetos que son claves/valores.
Este ejemplo muestra cómo WeakMap elimina automáticamente las entradas cuando los objetos ya no tienen referencias. Al asignar null a la variable, el objeto se vuelve elegible para el garbage collector, y WeakMap elimina la entrada correspondiente.
Cuándo Ocurre la Recolección
La recolección de basura ocurre cuando el garbage collector determina que un objeto ya no es accesible desde tu código. Esto puede ser porque todas las referencias al objeto fueron eliminadas o porque la variable que lo contenía fue reasignada.
Este ejemplo muestra diferentes escenarios donde ocurre la recolección de basura. Cuando eliminas todas las referencias o reasignas la variable, el objeto se vuelve elegible para el garbage collector, y WeakMap/WeakSet eliminan las entradas correspondientes.
Ventaja de Performance
WeakMap y WeakSet ayudan a evitar fugas de memoria en aplicaciones complejas. Al permitir la recolección automática de objetos que ya no se usan, evitas mantener datos innecesarios en memoria, lo que mejora el rendimiento general de la aplicación.
Diferencias con Map y Set
Es importante entender las diferencias clave entre WeakMap/WeakSet y sus contrapartes Map/Set. Estas diferencias determinan cuándo usar una u otra estructura de datos.
Tabla Comparativa
Esta tabla muestra las diferencias principales entre WeakMap/WeakSet y Map/Set. Entender estas diferencias es crucial para elegir la estructura de datos correcta para tu caso de uso.
Las diferencias principales son: WeakMap/WeakSet solo aceptan objetos, no son iterables, y permiten la recolección automática. Map/Set aceptan cualquier tipo de valor, son iterables, y mantienen referencias fuertes.
- WeakMap/WeakSet: solo objetos, no iterable, recolección automática
- Map/Set: cualquier tipo, iterable, referencias fuertes
- WeakMap/WeakSet: no size, forEach, entries(), keys(), values()
- Map/Set: size, forEach, entries(), keys(), values() disponibles
- WeakMap/WeakSet: ideal para cachés y metadatos
- Map/Set: ideal para datos persistentes y operaciones de conjuntos
Cuándo Usar Cada Uno
La elección entre WeakMap/WeakSet y Map/Set depende de tu caso de uso específico. WeakMap/WeakSet son ideales para cachés y metadatos, mientras que Map/Set son mejores para datos persistentes y operaciones que requieren iteración.
Este ejemplo muestra cuándo usar WeakMap para cachés y cuándo usar Map para datos persistentes. La clave es si necesitas que los datos se recolecten automáticamente (WeakMap/WeakSet) o si necesitas que persistan y sean iterables (Map/Set).
Regla General
Usa WeakMap/WeakSet cuando necesitas cachés o metadatos de objetos que puedan recolectarse automáticamente. Usa Map/Set cuando necesitas datos persistentes, iteración o métodos como size, forEach, entries().
Casos de Uso Prácticos
WeakMap y WeakSet brillan en escenarios específicos donde las fugas de memoria son un problema. Estos casos de uso demuestran cómo estas colecciones pueden resolver problemas reales de manera más elegante y eficiente.
Cache de Objetos
WeakMap es ideal para implementar cachés de objetos que se recolectan automáticamente. Esto evita fugas de memoria porque los objetos en el caché se eliminan cuando ya no se usan en la aplicación.
Este ejemplo muestra cómo usar WeakMap como caché para objetos. Cuando un objeto ya no se usa en la aplicación, se elimina automáticamente del caché, liberando memoria. Esto es mucho más eficiente que usar Map regular que requeriría limpieza manual.
Metadatos de Elementos DOM
WeakMap es excelente para asociar metadatos con elementos DOM sin causar fugas de memoria. Cuando los elementos se eliminan del DOM, los metadatos se recolectan automáticamente.
Este ejemplo muestra cómo usar WeakMap para metadatos de elementos DOM. Cuando eliminas un elemento del DOM, los metadatos correspondientes se eliminan automáticamente, evitando fugas de memoria en aplicaciones con manipulación intensiva del DOM.
Registros de Eventos
WeakSet es ideal para mantener registros de objetos que se recolectan automáticamente. Esto es útil para rastrear objetos activos sin causar fugas de memoria cuando se vuelven inactivos.
Este ejemplo muestra cómo usar WeakSet para mantener registros de objetos activos. Cuando un objeto se vuelve inactivo y se elimina del registro, WeakSet lo elimina automáticamente, liberando memoria. WeakMap y WeakSet son especialmente útiles en aplicaciones complejas con muchos objetos temporales, donde la recolección automática mejora significativamente el rendimiento y la estabilidad.
Errores Comunes
Al trabajar con WeakMap y WeakSet, existen ciertos errores comunes que pueden causar bugs difíciles de detectar. Conocer estos errores te ayudará a escribir código más robusto y evitar problemas en producción.
Usar Primitivos como Claves/Valores
Un error común es intentar usar primitivos como claves en WeakMap o como valores en WeakSet. Esto causará un error porque solo aceptan objetos.
WeakMap solo acepta objetos como claves, y WeakSet solo acepta objetos como valores. Intentar usar primitivos como strings, números o booleanos causará un error. Debes usar Map o Set regular si necesitas primitivos.
Solo Objetos Permitidos
WeakMap y WeakSet solo aceptan objetos como claves/valores. No puedes usar strings, números, booleanos, null o undefined. Si necesitas estos tipos, usa Map o Set regular.
Intentar Iterar WeakMap/WeakSet
Otro error común es intentar iterar sobre WeakMap o WeakSet con for...of o forEach. Esto no es posible porque no son iterables.
WeakMap y WeakSet no son iterables y no tienen métodos como forEach, entries(), keys(), values(). Solo puedes acceder a valores específicos usando get() y verificar existencia con has(). Si necesitas iteración, usa Map o Set regular. Esta limitación es por diseño, ya que la naturaleza de las referencias débiles hace imposible garantizar qué elementos existen en un momento dado.
Confundir Fugas de Memoria
Es importante entender que WeakMap y WeakSet no eliminan automáticamente todas las fugas de memoria. Solo eliminan entradas cuando los objetos ya no tienen referencias activas.
Este ejemplo muestra que WeakMap no previene todas las fugas de memoria. Si creas una fuga de memoria (por ejemplo, un array que crece indefinidamente), WeakMap no la corregirá automáticamente. Debes asegurarte de eliminar las referencias manualmente.
Resumen: WeakMap y WeakSet en JavaScript
Conceptos principales:
- •WeakMap/WeakSet solo aceptan objetos como claves/valores
- •Mantiene referencias débiles que se recolectan automáticamente
- •No son iterables: no tienen size, forEach, entries()
- •Métodos principales: set(), get(), has(), delete() para WeakMap
- •Métodos principales: add(), has(), delete() para WeakSet
Mejores prácticas:
- •Usa WeakMap para cachés de objetos que se recolecten automáticamente
- •Usa WeakSet para registros de objetos que se recolecten automáticamente
- •Usa Map o Set regular cuando necesites iteración o primitivos
- •Elimina manualmente las referencias para liberar memoria cuando sea necesario
- •No uses WeakMap/WeakSet para datos persistentes que deben mantenerse