Obiectul Proxy permite învelirea (wrapping-ul) unui obiect țintă pentru a intercepta și personaliza operațiunile fundamentale efectuate asupra acestuia: citirea de proprietăți (get), scrierea de valori (set), ștergerea (deleteProperty), verificarea existenței (has) sau apelarea ca funcție (apply).
Împreună cu obiectul însoțitor Reflect (care conține metodele native corespunzătoare pentru delegarea acțiunii implicite), Proxy stă la baza celor mai populare sisteme de reactivitate modernă (inclusiv motorul de reactivitate din Vue 3 și MobX).
Construirea unui mini-sistem de Reactivitate și Validare cu Proxy
const dateUtilizator = {
nume: 'Maria',
varsta: 25
};
// Creăm un Proxy care validează datele la scriere și declanșează actualizarea interfeței:
const utilizatorReactiv = new Proxy(dateUtilizator, {
// Interceptăm citirea de proprietăți (get)
get(target, proprietate, receiver) {
console.log(`[GET] S-a citit proprietatea '${proprietate}'`);
return Reflect.get(target, proprietate, receiver);
},
// Interceptăm modificarea sau adăugarea de proprietăți (set)
set(target, proprietate, valoare, receiver) {
if (proprietate === 'varsta') {
if (typeof valoare !== 'number' || valoare <= 0) {
throw new TypeError("Vârsta trebuie să fie un număr pozitiv valid!");
}
}
console.log(`[SET] Proprietatea '${proprietate}' s-a schimbat în: ${valoare}`);
// Delegăm scrierea efectivă către Reflect
const succes = Reflect.set(target, proprietate, valoare, receiver);
// Simulăm declanșarea re-randării interfeței utilizator:
if (succes) {
document.title = `Profil: ${target.nume} (${target.varsta} ani)`;
}
return succes;
}
});
// Utilizare:
console.log(utilizatorReactiv.nume); // Afișează: [GET] S-a citit proprietatea 'nume' -> Maria
utilizatorReactiv.varsta = 26; // Afișează: [SET] Proprietatea 'varsta' s-a schimbat în: 26
// Tentativă de setare invalidă:
// utilizatorReactiv.varsta = -5; // Aruncă TypeError: Vârsta trebuie să fie un număr pozitiv valid!
Cele Mai Frecvente Trap-uri Proxy
| Trap Proxy | Operațiune interceptată | Echivalent Reflect |
|---|---|---|
get(target, prop, receiver) |
Citirea valorii: obj.prop |
Reflect.get(...) |
set(target, prop, val, receiver) |
Scrierea valorii: obj.prop = val |
Reflect.set(...) |
has(target, prop) |
Operatorul in: 'prop' in obj |
Reflect.has(...) |
deleteProperty(target, prop) |
Operatorul delete: delete obj.prop |
Reflect.deleteProperty(...) |