Proxy y Reflect en JavaScript
Proxy
Un objeto Proxy en JavaScript permite envolver otro objeto y interceptar sus operaciones, como lectura y escritura de propiedades. Esto proporciona un control más granular sobre la interacción con el objeto original.
Sintaxis
let proxy = new Proxy(target, handler)
- target: El objeto a envolver.
- handler: Objeto que define las trampas (métodos que interceptan operaciones).
Ejemplo básico
let target = {};
let proxy = new Proxy(target, {}); // manejador vacío
proxy.test = 5; // Escribiendo en el proxy
alert(target.test); // 5, la propiedad aparece en target
alert(proxy.test); // 5, se puede leer desde el proxy
for(let key in proxy) alert(key); // test, la iteración funciona
Trampas comunes
- get(target, property, receiver): Intercepta la lectura de una propiedad.
- set(target, property, value, receiver): Intercepta la escritura de una propiedad.
- has(target, property): Intercepta el operador
in
. - deleteProperty(target, property): Intercepta el operador
delete
. - ownKeys(target): Intercepta métodos que iteran sobre propiedades (e.g.,
Object.keys
).
Ejemplos prácticos
Valores por defecto con get
let numbers = [0, 1, 2];
numbers = new Proxy(numbers, {
get(target, prop) {
return prop in target ? target[prop] : 0;
}
});
alert(numbers[1]); // 1
alert(numbers[123]); // 0
Validación con set
let numbers = [];
numbers = new Proxy(numbers, {
set(target, prop, val) {
if (typeof val === 'number') {
target[prop] = val;
return true;
} else {
throw new TypeError("Debe ser un número");
}
}
});
numbers.push(1); // Añadido correctamente
numbers.push("test"); // Error: Debe ser un número
Propiedades protegidas con varias trampas
let user = {
name: "John",
_password: "***"
};
user = new Proxy(user, {
get(target, prop) {
if (prop.startsWith('_')) {
throw new Error("Acceso denegado");
}
return target[prop];
},
set(target, prop, val) {
if (prop.startsWith('_')) {
throw new Error("Acceso denegado");
} else {
target[prop] = val;
return true;
}
},
deleteProperty(target, prop) {
if (prop.startsWith('_')) {
throw new Error("Acceso denegado");
} else {
delete target[prop];
return true;
}
},
ownKeys(target) {
return Object.keys(target).filter(key => !key.startsWith('_'));
}
});
Reflect
Reflect es un objeto nativo que proporciona una forma de invocar los métodos internos de los objetos de manera más directa. Simplifica la creación de proxies al permitir redirigir operaciones al objeto original.
Ejemplos de uso
let user = {
name: "John",
};
user = new Proxy(user, {
get(target, prop, receiver) {
alert(`GET ${prop}`);
return Reflect.get(target, prop, receiver);
},
set(target, prop, value, receiver) {
alert(`SET ${prop} = ${value}`);
return Reflect.set(target, prop, value, receiver);
}
});
user.name; // GET name
user.age = 30; // SET age = 30
Resumen de métodos Reflect
- Reflect.get(target, prop, receiver)
- Reflect.set(target, prop, value, receiver)
- Reflect.deleteProperty(target, prop)
- Reflect.construct(target, args)
Reflect hace que sea fácil reenviar operaciones interceptadas por trampas Proxy al objeto original, manteniendo el comportamiento esperado del objeto envolvente.
Estos conceptos y ejemplos muestran cómo Proxy y Reflect pueden ser utilizados para controlar y extender el comportamiento de los objetos en JavaScript de manera flexible y poderosa.