La metaprogramación es un paradigma de programación poderoso que permite que el código manipule dinámicamente su comportamiento en tiempo de ejecución. JavaScript, con la introducción de Proxies y la API Reflect en ES6, ha llevado las capacidades de metaprogramación a un nuevo nivel, permitiendo a los desarrolladores interceptar y redefinir operaciones básicas de objetos como el acceso a propiedades, asignación e invocación de funciones.
Esta publicación de blog profundiza en estas características avanzadas de JavaScript, explicando su sintaxis, casos de uso y cómo trabajan juntas para potenciar la programación dinámica.
¿Qué son los Proxies?
Un Proxy en JavaScript es un envoltorio que permite a los desarrolladores interceptar y personalizar operaciones fundamentales realizadas en un objeto. Estas operaciones incluyen la obtención y configuración de propiedades, llamadas a funciones, eliminación de propiedades y más.
Sintaxis de Proxy
const proxy = new Proxy(target, handler);
target
: El objeto que está siendo proxificado.handler
: Un objeto que contiene métodos, conocidos como trampas, que definen comportamientos personalizados para operaciones interceptadas.
Ejemplo: Registro de Acceso a Propiedades
const user = { name: 'Alice', age: 30 };
const proxy = new Proxy(user, {
get(target, property) {
console.log(`Accessing property: ${property}`);
return target[property];
}
});
console.log(proxy.name); // Logs: Accessing property: name → Output: Alice
Trampas Clave de Proxy
Trap Name | Operation Intercepted |
---|---|
get |
Acceder a una propiedad (obj.prop o obj['prop'] ) |
set |
Asignar un valor a una propiedad (obj.prop = valor ) |
deleteProperty |
Eliminar una propiedad (delete obj.prop ) |
has |
Comprobando la existencia de una propiedad (prop in obj ) |
apply |
Invocación de una función (obj() ) |
construct |
Creando nuevas instancias con new (new obj() ) |
Casos de Uso Avanzados con Proxies
1. Validación de Entrada
const user = { age: 25 };
const proxy = new Proxy(user, {
set(target, property, value) {
if (property === 'age' && typeof value !== 'number') {
throw new Error('Age must be a number!');
}
target[property] = value;
return true;
}
});
proxy.age = 30; // Works fine
proxy.age = '30'; // Throws Error: Age must be a number!
En este ejemplo, el trap set
asegura la validación del tipo antes de permitir asignaciones.
2. Sistemas Reactivos (Similar a la Reactividad de Vue.js)
const data = { price: 5, quantity: 2 };
let total = 0;
const proxy = new Proxy(data, {
set(target, property, value) {
target[property] = value;
total = target.price * target.quantity;
console.log(`Total updated: ${total}`);
return true;
}
});
proxy.price = 10; // Logs: Total updated: 20
proxy.quantity = 3; // Logs: Total updated: 30
Este código recalcula dinámicamente valores cada vez que las propiedades dependientes son actualizadas, imitando el comportamiento de los modernos frameworks reactivos.
¿Qué es Reflect?
La API Reflect complementa a los Proxies proporcionando métodos que realizan comportamientos predeterminados para operaciones de objetos, facilitando su integración en los traps de Proxy.
Métodos Clave de Reflect
Method | Description |
---|---|
Reflect.get(target, prop) |
Recupera el valor de una propiedad. |
Reflect.set(target, prop, val) |
Establece el valor de una propiedad. |
Reflect.has(target, prop) |
Verifica la existencia de una propiedad (prop in obj ). |
Reflect.deleteProperty(target, prop) |
Elimina una propiedad. |
Reflect.apply(func, thisArg, args) |
Llama a una función con un this contexto especificado. |
Reflect.construct(target, args) |
Crea una nueva instancia de un constructor. |
Ejemplo: Uso de Reflect para Comportamiento por Defecto
const user = { age: 25 };
const proxy = new Proxy(user, {
set(target, property, value) {
if (property === 'age' && typeof value !== 'number') {
throw new Error('Age must be a number!');
}
return Reflect.set(target, property, value); // Default behavior
}
});
proxy.age = 28; // Sets successfully
console.log(user.age); // Output: 28
Usar Reflect simplifica el código al mantener operaciones por defecto y añadir lógica personalizada.
Casos de Uso en el Mundo Real
- Envolturas de seguridad: Restringir el acceso a propiedades sensibles.
- Registro y depuración: Seguir cambios en objetos.
- Validación de datos de API: Asegurar reglas estrictas para los datos de la API.
Conclusión
La metaprogramación con Proxies y Reflect permite a los desarrolladores controlar y modificar dinámicamente el comportamiento de la aplicación. Domina estas herramientas para mejorar tu experiencia en JavaScript.
¡Feliz codificación!
Source:
https://dzone.com/articles/metaprogramming-proxies-reflect-javascript