WeakRefs y Finalizers en JavaScript
Tags: javascript, es2021, espanol, spanish
Published: 2020-10-08 23:21:08

---
title: WeakRefs y Finalizers en JavaScript
published: true
description: "Un objeto weakRef permite mantener una referencia débil a otro objeto sin prevenir que este objeto sea eliminado de la memoria por el recolector de basura y FinalizationRegistry nos permite hacer un *callback* cuando este objeto ha sido debidamente recolectado."
tags: 
  - "JavaScript"
  - "es2021"
  - "espanol"
  - "spanish"
canonical_url: https://alfredobonilla.dev/blog/weakrefs-y-finalizers-en-javascript
---


WeakRefs y Finalizers es una nueva característica de JavaScript añadida como parte de ES2021, su funcionamiento es bastante interesante pero puede ser complejo y no debe utilizarse si no es estrictamente necesario, a continuación veremos un poco más sobre esto.

---

## 🏁 **TL;DR**

En JavaScript las referencias a objetos son respetadas por el recolector de basura (o _garbage collector_), es decir, si el algoritmo de recolección encuentra que un objeto es alcanzable desde un objeto raíz este no será recolectado, pero si el objeto es inalcanzable, este será recolectado.

Se puede decir que este proceso es una aproximación ya que el algoritmo no puede saber a ciencia cierta si un objeto es necesario o no.

Un objeto `weakRef` permite mantener una referencia débil a otro objeto sin prevenir que este objeto sea eliminado de la memoria por el recolector de basura y `FinalizationRegistry` nos permite hacer un _callback_ cuando este objeto ha sido debidamente recolectado.

---

## 📦 Gestión de la memoria en JavaScript

El ciclo de vida de la memoria es muy parecido en todos los lenguajes de programación primero se reserva la memoria necesaria, se utiliza y luego se libera cuando ya no es necesaria.

JavaScript asigna memoria de manera automática cada vez que se declara un valor al igual que la liberación de memoria no utilizada se realiza automáticamente por medio del Recolector de Basura o _Garbage Collector._

## 🔗 WeakRefs

Una `weakRef` es un objeto que tiene una referencia débil a un objeto llamado referente u objetivo, esta referencia permite que el objeto sea recolectado por el _garbage collector._

Cabe mencionar que se debe tener cuidado al utilizar las referencias débiles, de hecho es bueno evitarlas de ser posible. También debemos saber que el comportamiento del garbage collector puede cambiar de motor a motor y podría ser diferente para diferentes versiones del motor de JavaScript.

En otras palabras, el momento y la manera en que la recolección sucede puede variar y eso puede afectar el resultado que esperamos, incluso podría suceder que el método `deref` nunca retorne `undefined` debido a que el recolector decidió nunca recolectar esa referencia.

### 📣 FinalizationRegistry

FinalizationRegistry es un objeto que permite ejecutar un callback cuando un objeto es recolectado. Si el objetivo de un FinalizationRegistry es también un elemento con una WeakRef entonces la referencia se eliminará al mismo tiempo que la ejecución del callback por lo que no será posible obtener la referencia del objeto dentro del callback.

### ⚙️ Ejemplo

Este es un ejemplo simple donde vamos a definir una referencia débil para un objeto que va a contener una animación generada a partir de otros elementos del DOM que se adjuntan segundo a segundo durante 5 segundos.

Una vez que el tiempo haya pasado, la referencia será recolectada y se disparará un callback indicando que el objeto fue recolectado.

```jsx
class CircleAnimation {
  constructor(element) {
    // Define una referencia débil a un elemento del DOM.
    this.ref = new WeakRef(element)

    // Define un callback que se ejecutara
    // cuando el elemento de referencia débil sea recolectado.
    this.registry = new FinalizationRegistry((hadValue) =>
      console.log("Referencia recolectada: ", hadValue)
    )
    this.registry.register(element, "Elemento de animación")

    this.start()
  }

  start() {
    if (this.timer) {
      return
    }

    const addCircle = () => {
      // Obtiene el elemento de la referencia.
      const referencedElement = this.ref.deref()
      if (referencedElement) {
        const circle = document.createElement("div")
        circle.className = "circle"
        referencedElement.append(circle)
      } else {
        // El elemento ya no existe.
        console.log("El elemento ya no existe.")
        this.stop()
        this.ref = null
      }
    }

    addCircle()
    this.timer = setInterval(addCircle, 1000)
  }

  stop() {
    if (this.timer) {
      clearInterval(this.timer)
      this.timer = 0
    }
  }
}

const animation = new CircleAnimation(document.getElementById("app"))
animation.start()

setTimeout(() => {
  document.getElementById("app").remove()
}, 5000)
```

💻 El ejemplo completo se encuentra [aquí](https://stackblitz.com/edit/es2021-weak-reference).

‼️ Para poder observar su funcionamiento correctamente es necesario recargar la página cada vez que se ejecuta la animación.

¿Se les ocurre algún uso para esta característica? Dejen sus comentarios y opiniones sobre el tema.

Puedes encontrar el artículo original en mi [blog](https://alfredobonilla.dev/blog/weakrefs-y-finalizers-en-javascript). 

¡Hasta la próxima! 😉