W3docs

JavaScript Proxy e Reflect

Scopri come funzionano JavaScript Proxy e Reflect: intercetta operazioni get, set, apply, has e delete con le trap, e applica i proxy per validazione, controllo accessi e logging.

I proxy di JavaScript ti permettono di intercettare e ridefinire le operazioni fondamentali sugli object — leggere una proprietà, scriverne una, verificare l'esistenza di una chiave, chiamare una funzione e altro ancora. Abbinati all'API Reflect, che esegue quelle stesse operazioni nel modo "predefinito", i proxy offrono un meccanismo pulito e ufficiale per aggiungere comportamenti agli object senza modificarli direttamente.

Questo capitolo tratta cos'è un proxy, le trap più comuni (get, set, apply, has, deleteProperty), come Reflect complementa i proxy e diversi pattern reali come validazione, controllo degli accessi e logging.

Cos'è un Proxy

Un Proxy avvolge un oggetto target e un handler. L'handler è un insieme di funzioni chiamate trap, ciascuna delle quali intercetta un'operazione specifica. Quando interagisci con il proxy, viene eseguita la trap corrispondente al posto del comportamento predefinito; se per un'operazione non è definita alcuna trap, il proxy la inoltra al target senza modifiche.

Questo è utile quando vuoi aggiungere comportamenti trasversali — logging, validazione, valori predefiniti, regole di accesso — a un object senza toccare il suo codice.

Sintassi del Proxy

const proxy = new Proxy(target, handler);
  • target: L'object originale le cui operazioni vuoi intercettare.
  • handler: Un object i cui metodi (trap) definiscono come si comportano le operazioni.

Utilizzi quindi proxy esattamente come faresti con l'object originale; la differenza è che le tue trap vengono eseguite nel mezzo.

La Trap get

La trap get intercetta le letture di proprietà sull'object target. Riceve il target, la chiave property e il receiver (il proxy stesso). Viene spesso usata per registrare gli accessi, calcolare proprietà al volo o restituire valori predefiniti per chiavi mancanti.

Esempio:

javascript— editable

Questo codice imposta un proxy per registrare gli accessi alle proprietà di un object.

  • Handler: Definisce una trap get per registrare la proprietà a cui si accede.
  • Object Target: Contiene le proprietà name e age.
  • Proxy: Avvolge l'object target con l'handler.

Quando si accede a proxy.name, viene registrato "Getting name" e restituito "John". Questo è utile per monitorare o fare debug degli accessi alle proprietà.

Manipolazione delle Operazioni sugli Object con le Trap set e apply

La Trap set

La trap set può applicare regole per le assegnazioni di proprietà, assicurando che le proprietà contengano tipi specifici o soddisfino determinate condizioni.

Esempio:

javascript— editable

Questo codice imposta un proxy per validare e registrare le assegnazioni di proprietà su un object.

  • Handler: Definisce una trap set per verificare la proprietà age con valori validi e registrare i tentativi di impostarla.
  • Proxy: Avvolge l'object target con l'handler.

Quando si imposta proxy.age, verifica se si tratta di un'età valida (0-150). Se non è valida, registra un errore e lancia un'eccezione.

La Trap apply

Il metodo apply in un JavaScript Proxy intercetta le chiamate di funzione. Accetta tre argomenti:

  1. target: La funzione originale che viene chiamata.
  2. thisArg: Il valore di this all'interno della funzione.
  3. argumentsList: Un array di argomenti passati alla funzione.

Esempio:

javascript— editable

Questo codice imposta un proxy per registrare le chiamate di funzione e i relativi argomenti.

  • Handler: Definisce una trap apply per registrare gli argomenti quando la funzione viene chiamata.
  • Funzione: sum somma due numeri.
  • Proxy: Avvolge la funzione sum con l'handler.

Nel codice fornito, la trap apply registra gli argomenti e poi chiama la funzione originale usando target.apply(thisArg, argumentsList). Questo è utile per il logging, il debug o la modifica dinamica del comportamento delle funzioni.

La Trap has

La trap has intercetta l'operatore in. Un utilizzo comune è nascondere le chiavi "private" (per convenzione, i nomi che iniziano con _) in modo che non sembrino esistere dall'esterno.

Esempio:

javascript— editable

Anche se _secret esiste ancora sul target, l'operatore in restituisce false, quindi la chiave è effettivamente nascosta al codice che esamina l'object.

La Trap deleteProperty

La trap deleteProperty intercetta l'operatore delete, permettendoti di proteggere determinate chiavi dalla rimozione. Deve restituire true quando l'eliminazione è consentita, oppure lanciare un'eccezione per bloccarla in modalità strict.

Esempio:

javascript— editable
Attenzione

I proxy JavaScript sono potenti, ma usali con saggezza. L'uso eccessivo dei proxy può rendere il tuo codice più difficile da comprendere e mantenere. Tieni presente che i proxy introducono un leggero overhead di prestazioni rispetto agli object nativi.

API Reflect

Reflect è un object integrato che fornisce un metodo per ogni operazione intercettabile — lo stesso insieme esatto coperto dalle trap dei proxy (Reflect.get, Reflect.set, Reflect.has, Reflect.deleteProperty, Reflect.apply e così via). Ogni metodo esegue la versione predefinita di quell'operazione.

Questo rende Reflect il complemento naturale di Proxy: all'interno di una trap di solito vuoi aggiungere un comportamento e poi lasciare che l'operazione proceda normalmente. Chiamare il metodo Reflect corrispondente fa esattamente questo, e inoltra il receiver correttamente (importante per getter/setter), cosa che un semplice target[property] non fa. Vedrai questo pattern usato negli esempi pratici qui sotto.

I metodi di Reflect restituiscono anche valori invece di lanciare eccezioni — per esempio Reflect.set restituisce un boolean che indica il successo — il che rende le operazioni più prevedibili rispetto ai loro equivalenti con operatori o Object.*.

Ecco una rapida panoramica dei principali metodi Reflect:

1. Reflect.get()

Questo metodo viene usato per ottenere il valore di una proprietà da un object.

Esempio:

javascript— editable

2. Reflect.set()

Questo metodo viene usato per impostare il valore di una proprietà su un object.

Esempio:

javascript— editable

3. Reflect.has()

Questo metodo verifica se una proprietà esiste in un object.

Esempio:

javascript— editable

4. Reflect.deleteProperty()

Questo metodo elimina una proprietà da un object.

Esempio:

javascript— editable

5. Reflect.ownKeys()

Questo metodo restituisce tutte le chiavi di proprietà proprie di un object.

Esempio:

javascript— editable

6. Reflect.apply()

Questo metodo chiama una funzione target con gli argomenti forniti.

Esempio:

javascript— editable

7. Reflect.construct()

Questo metodo viene usato per creare una nuova istanza di un object.

Esempio:

javascript— editable

Questi esempi mostrano come usare i metodi Reflect per eseguire operazioni comuni sugli object in modo più pulito e coerente.

Casi d'Uso Pratici dei Proxy JavaScript

Esempio 1: Inizializzazione Automatica delle Proprietà

Descrizione: Usa i proxy JavaScript per inizializzare automaticamente le proprietà undefined in un object. Questo può essere utile nelle situazioni in cui gli object vengono riempiti dinamicamente con dati nel tempo, come le impostazioni utente o le configurazioni che potrebbero non essere impostate inizialmente.

javascript— editable

Questo codice crea un proxy che verifica se una proprietà esiste su un object. Se non esiste, il proxy imposta automaticamente un valore predefinito per essa. Questo è utile per prevenire errori dovuti a proprietà mancanti.

Esempio 2: Controllo degli Accessi

Descrizione: I proxy possono applicare permessi di lettura o scrittura sulle proprietà degli object. Questo esempio dimostra un proxy che impedisce la lettura o la scrittura di determinate proprietà in base a regole predefinite, il che è particolarmente utile per gestire l'accesso a dati sensibili.

javascript— editable

Questo codice protegge un object controllando l'accesso alle sue proprietà. Blocca la lettura di 'sensitiveData' e impedisce la modifica delle proprietà 'readOnly', contribuendo a mantenere i dati al sicuro.

Esempio 3: Logging e Debug

Descrizione: I proxy possono essere usati per registrare le interazioni con un object, il che aiuta nel debug e nel monitoraggio delle operazioni. Questo esempio crea un proxy che registra tutti i get, set e le chiamate ai metodi eseguite su un object.

javascript— editable

Questo codice tiene traccia di ogni volta che qualcuno accede o modifica una proprietà sull'object, il che è ottimo per capire cosa sta facendo il tuo codice e quando.

Esempio 4: Validazione dei Dati

Descrizione: Usa i proxy per la validazione al volo delle proprietà degli object. Questo è particolarmente utile per garantire l'integrità dei dati quando gli object vengono aggiornati dinamicamente in un'applicazione.

javascript— editable

Questo esempio dimostra come usare il Proxy di JavaScript per validare e registrare le modifiche alle proprietà. L'object validator verifica se la proprietà age è un numero valido compreso tra 0 e 150. In caso contrario, registra un errore e lancia un'eccezione. Altrimenti, registra il nuovo valore e aggiorna la proprietà. L'object person usa questo validator per gestire la sua proprietà age, assicurando che le età non valide vengano intercettate e registrate.

Conclusione

Padroneggiare i proxy JavaScript ti permette di controllare ed estendere il comportamento degli object senza modificarli direttamente. I proxy possono applicare regole di validazione e accesso, fornire valori predefiniti e alimentare strumenti di logging o debug, mentre Reflect mantiene le operazioni sottostanti pulite e prevedibili. Usati con parsimonia, ti aiutano a creare applicazioni più dinamiche e sicure.

Per approfondire le operazioni che i proxy intercettano, consulta getter e setter di proprietà e flag e descrittori di proprietà. Per il pattern di validazione mostrato sopra, gestione degli errori con try...catch e le classi sono complementi utili.

Esercitazione

Pratica
Qual è la funzionalità principale degli object Proxy e Reflect di JavaScript?
Qual è la funzionalità principale degli object Proxy e Reflect di JavaScript?
Was this page helpful?