W3docs

JavaScript Proxy y Reflect

Aprende cómo funcionan JavaScript Proxy y Reflect: intercepta operaciones get, set, apply, has y delete con traps, y aplica proxies para validación, control de acceso y registro.

Los proxies de JavaScript te permiten interceptar y redefinir las operaciones fundamentales sobre objects — leer una propiedad, escribirla, comprobar si existe una clave, llamar a una función, y más. Combinados con la API Reflect, que realiza esas mismas operaciones de forma "predeterminada", los proxies te ofrecen un mecanismo oficial y limpio para añadir comportamiento a los objects sin modificarlos directamente.

Este capítulo cubre qué es un proxy, los traps más comunes (get, set, apply, has, deleteProperty), cómo Reflect complementa a los proxies, y varios patrones prácticos como validación, control de acceso y registro.

Qué es un Proxy

Un Proxy envuelve un objeto target y un handler. El handler es un conjunto de funciones llamadas traps, cada una interceptando una operación específica. Cuando interactúas con el proxy, el trap correspondiente se ejecuta en lugar del comportamiento predeterminado; si no se define ningún trap para una operación, el proxy la reenvía al target sin cambios.

Esto es útil cuando quieres añadir comportamiento transversal — registro, validación, valores predeterminados, reglas de acceso — a un object sin tocar su propio código.

Sintaxis de Proxy

const proxy = new Proxy(target, handler);
  • target: El object original cuyas operaciones quieres interceptar.
  • handler: Un object cuyos métodos (traps) definen cómo se comportan las operaciones.

Luego usas proxy exactamente como usarías el object original; la diferencia es que tus traps se ejecutan en medio.

Comprendiendo el Trap get

El trap get intercepta las lecturas de propiedades sobre el object target. Recibe el target, la clave de property y el receiver (el propio proxy). Se usa frecuentemente para registrar accesos, calcular propiedades al vuelo, o devolver valores predeterminados para claves ausentes.

Ejemplo:

javascript— editable

Este código configura un proxy para registrar los accesos a propiedades de un object.

  • Handler: Define un trap get para registrar la propiedad accedida.
  • Object target: Contiene las propiedades name y age.
  • Proxy: Envuelve el object target con el handler.

Cuando se accede a proxy.name, registra "Getting name" y devuelve "John". Esto es útil para monitorizar o depurar accesos a propiedades.

Manipulando Operaciones de Object con los Traps set y apply

El Trap set

El trap set puede imponer reglas para las asignaciones de propiedades, asegurando que las propiedades contengan tipos específicos o cumplan ciertas condiciones.

Ejemplo:

javascript— editable

Este código configura un proxy para validar y registrar las asignaciones de propiedades sobre un object.

  • Handler: Define un trap set para comprobar la propiedad age en busca de valores válidos y registrar los intentos de asignarla.
  • Proxy: Envuelve el object target con el handler.

Cuando se asigna proxy.age, comprueba si es una edad válida (0-150). Si es inválida, registra un error y lanza una excepción.

El Trap apply

El método apply en un JavaScript Proxy intercepta las llamadas a funciones. Recibe tres argumentos:

  1. target: La función original que se está llamando.
  2. thisArg: El valor de this dentro de la función.
  3. argumentsList: Un array de argumentos pasados a la función.

Ejemplo:

javascript— editable

Este código configura un proxy para registrar las llamadas a funciones y sus argumentos.

  • Handler: Define un trap apply para registrar los argumentos cuando se llama a la función.
  • Función: sum suma dos números.
  • Proxy: Envuelve la función sum con el handler.

En el código proporcionado, el trap apply registra los argumentos y luego llama a la función original usando target.apply(thisArg, argumentsList). Esto es útil para registro, depuración o modificación dinámica del comportamiento de funciones.

El Trap has

El trap has intercepta el operador in. Un uso común es ocultar claves "privadas" (por convención, nombres que comienzan con _) para que no parezcan existir desde el exterior.

Ejemplo:

javascript— editable

Aunque _secret sigue existiendo en el target, el operador in devuelve false, por lo que la clave queda efectivamente oculta para el código que examina el object.

El Trap deleteProperty

El trap deleteProperty intercepta el operador delete, permitiéndote proteger ciertas claves de ser eliminadas. Debe devolver true cuando la eliminación está permitida, o lanzar un error para bloquearla en modo estricto.

Ejemplo:

javascript— editable
Advertencia

Los proxies de JavaScript son poderosos, pero úsalos con criterio. El uso excesivo de proxies puede hacer que tu código sea más difícil de entender y mantener. Ten en cuenta que los proxies introducen una ligera sobrecarga de rendimiento en comparación con los objects nativos.

API Reflect

Reflect es un object integrado que proporciona un método para cada operación interceptable — el mismo conjunto exacto cubierto por los traps de proxy (Reflect.get, Reflect.set, Reflect.has, Reflect.deleteProperty, Reflect.apply, y así sucesivamente). Cada método realiza la versión predeterminada de esa operación.

Esto convierte a Reflect en el complemento natural de Proxy: dentro de un trap generalmente quieres añadir algún comportamiento y luego dejar que la operación proceda normalmente. Llamar al método Reflect correspondiente hace exactamente eso, y reenvía el receiver correctamente (importante para getters/setters), algo que un simple target[property] no hace. Verás este patrón utilizado en los ejemplos prácticos a continuación.

Los métodos Reflect también devuelven valores en lugar de lanzar excepciones — por ejemplo Reflect.set devuelve un boolean que indica éxito — lo que hace que las operaciones sean más predecibles que sus equivalentes de operador o Object.*.

Aquí tienes un recorrido rápido por los métodos clave de Reflect:

1. Reflect.get()

Este método se usa para obtener el valor de una propiedad de un object.

Ejemplo:

javascript— editable

2. Reflect.set()

Este método se usa para establecer el valor de una propiedad en un object.

Ejemplo:

javascript— editable

3. Reflect.has()

Este método comprueba si una propiedad existe en un object.

Ejemplo:

javascript— editable

4. Reflect.deleteProperty()

Este método elimina una propiedad de un object.

Ejemplo:

javascript— editable

5. Reflect.ownKeys()

Este método devuelve todas las claves de propiedades propias de un object.

Ejemplo:

javascript— editable

6. Reflect.apply()

Este método llama a una función target con los argumentos dados.

Ejemplo:

javascript— editable

7. Reflect.construct()

Este método se usa para crear una nueva instancia de un object.

Ejemplo:

javascript— editable

Estos ejemplos muestran cómo puedes usar los métodos Reflect para realizar operaciones comunes sobre objects de una manera más limpia y consistente.

Casos de Uso Prácticos de los Proxies de JavaScript

Ejemplo 1: Inicialización Automática de Propiedades

Descripción: Usa los proxies de JavaScript para inicializar automáticamente propiedades undefined en un object. Esto puede ser útil en situaciones donde los objects se llenan dinámicamente con datos con el tiempo, como configuraciones de usuario o ajustes que pueden no estar definidos inicialmente.

javascript— editable

Este código crea un proxy que comprueba si una propiedad existe en un object. Si no existe, el proxy establece automáticamente un valor predeterminado para ella. Esto ayuda a prevenir errores causados por propiedades ausentes.

Ejemplo 2: Control de Acceso

Descripción: Los proxies pueden imponer permisos de lectura o escritura sobre las propiedades de un object. Este ejemplo demuestra un proxy que impide que ciertas propiedades sean leídas o escritas en función de reglas predefinidas, lo que es especialmente útil para gestionar el acceso a datos sensibles.

javascript— editable

Este código protege un object controlando el acceso a sus propiedades. Bloquea la lectura de 'sensitiveData' e impide modificar las propiedades 'readOnly', ayudando a mantener los datos seguros.

Ejemplo 3: Registro y Depuración

Descripción: Los proxies pueden usarse para registrar las interacciones con un object, lo que ayuda en la depuración y monitorización de operaciones. Este ejemplo crea un proxy que registra todos los gets, sets y llamadas a métodos realizados sobre un object.

javascript— editable

Este código rastrea cada vez que alguien accede o cambia una propiedad del object, lo que es ideal para comprender qué hace tu código y cuándo.

Ejemplo 4: Validación de Datos

Descripción: Usa proxies para la validación al vuelo de las propiedades de un object. Esto es especialmente útil para garantizar la integridad de los datos cuando los objects se actualizan dinámicamente en una aplicación.

javascript— editable

Este ejemplo demuestra cómo usar el Proxy de JavaScript para validar y registrar cambios de propiedades. El object validator comprueba si la propiedad age es un número válido entre 0 y 150. Si no lo es, registra un error y lanza una excepción. En caso contrario, registra el nuevo valor y actualiza la propiedad. El object person usa este validador para gestionar su propiedad age, asegurando que las edades inválidas sean detectadas y registradas.

Conclusión

Dominar los proxies de JavaScript te permite controlar y extender el comportamiento de los objects sin modificarlos directamente. Los proxies pueden imponer validación y reglas de acceso, proporcionar valores predeterminados, y potenciar herramientas de registro o depuración, mientras que Reflect mantiene las operaciones subyacentes limpias y predecibles. Usados con moderación, te ayudan a construir aplicaciones más dinámicas y seguras.

Para profundizar en las operaciones que interceptan los proxies, consulta getters y setters de propiedades y flags y descriptores de propiedades. Para el patrón de validación mostrado anteriormente, el manejo de errores con try...catch y las clases son complementos útiles.

Práctica

Práctica
¿Cuál es la funcionalidad principal de los objetos Proxy y Reflect de JavaScript?
¿Cuál es la funcionalidad principal de los objetos Proxy y Reflect de JavaScript?
Was this page helpful?