Un oggetto Proxy racchiude un altro oggetto e ne intercetta le operazioni, come quelle di lettura/scrittura e molte altre; può eventualmente gestirle a modo suo oppure, in maniera del tutto trasparente, lasciare che sia l’oggetto ad occuparsene.
I proxy vengono utilizzati da molte librerie ed alcuni framework per browsers. Ne vedremo molte applicazioni pratiche in questo articolo.
Proxy
La sintassi:
let proxy = new Proxy(target, handler)
target– è l’oggetto da racchiudere; può essere qualsiasi cosa, anche una funzione.handler– configurazione del proxy: un oggetto con “trappole”, metodi che intercettano operazioni. Ad esempio una “trappola”getper la lettura di una proprietà ditarget,setper la scrittura di una proprietà ditarget, e così via.
Per le operazioni sul proxy, se c’è un “trappola” corrispondente in handler, allora questa verrà eseguita, e il proxy potrà gestirla, altrimenti l’operazione verrà eseguita su target.
Come primo esempio, creiamo un proxy senza “trappole”:
let target = {};
let proxy = new Proxy(target, {}); // handler vuoto
proxy.test = 5; // scrittura su proxy (1)
alert(target.test); // 5, la proprietà si trova su target!
alert(proxy.test); // 5, possiamo leggerla anche dal proxy (2)
for(let key in proxy) alert(key); // test, l'iterazione funziona (3)
Poiché non ci sono “trappole”, tutte le operazioni su proxy vengono inoltrate a target.
- Un’operazione di scrittura
proxy.test=imposta il valore sutarget. - Un’operazione di lettura
proxy.testritorna il valore datarget. - L’iterazione su
proxyritorna valori datarget.
Come possiamo vedere, senza “trappole”, proxy è solamente un contenitore per target.
Proxy è uno speciale “oggetto esotico”. Non possiede proprietà proprie. Con un handler vuoto, le operazioni verranno automaticamente inoltrate a target.
Per attivare più funzionalità, aggiungiamo qualche “trappola”.
Cosa possiamo intercettare?
Per molte operazioni sugli oggetti, esiste un così detto “metodo interno” nella specifiche JavaScript che ne descrive il funzionamento a basso livello. Ad esempio [[Get]], il metodo interno per la lettura delle proprietà, e [[Set]], il metodo interno per la scrittura delle proprietà, e così via. Questi metodi vengono utilizzati solamente nelle specifiche, non possiamo invocarli direttamente utilizzandone il nome.
Le trappole “proxy” intercettano le invocazioni di questi metodi. Queste vengono elencate nelle specifiche Proxy e nella tabella sottostante.
Per ogni metodo interno, esiste una “trappola” in questa tabella: il nome del metodo che possiamo aggiungere al parametro handler del new Proxy per intercettare l’operazione:
| Metodo Interno | Handler | Innescato quando… |
|---|---|---|
[[Get]] |
get |
lettura di un proprietà |
[[Set]] |
set |
scrittura di un proprietà |
[[HasProperty]] |
has |
operatore in |
[[Delete]] |
deleteProperty |
operatore delete |
[[Call]] |
apply |
invocazione di funzione |