Espressioni di Accesso alle Proprietà in JavaScript

Concetti Chiave
  • Le espressioni di accesso alle proprietà consentono di recuperare valori da oggetti e array in modo semplice e diretto.
  • L'accesso condizionale alle proprietà può essere utilizzato per evitare errori quando si accede a proprietà che potrebbero non esistere.
  • L'accesso alle proprietà può essere effettuato sia tramite notazione a punto che tramite notazione a parentesi quadre.
  • L'accesso alle proprietà può restituire undefined se la proprietà non esiste.

Espressioni di Accesso alle Proprietà

Un'espressione di accesso alle proprietà restituisce il valore di una proprietà di un oggetto o di un elemento di un array. JavaScript definisce due sintassi per l'accesso alle proprietà:

espressione . identificatore
espressione [ espressione ]

Il primo stile di accesso alle proprietà è un'espressione seguita da un punto e un identificatore. L'espressione specifica l'oggetto, e l'identificatore specifica il nome della proprietà desiderata. Il secondo stile di accesso alle proprietà segue la prima espressione (l'oggetto o array) con un'altra espressione tra parentesi quadre. Questa seconda espressione specifica il nome della proprietà desiderata o l'indice dell'elemento dell'array desiderato.

Ecco alcuni esempi concreti:

let o = {x: 1, y: {z: 3}}; // Un oggetto di esempio
let a = [o, 4, [5, 6]];    // Un array di esempio che contiene l'oggetto
o.x                        // => 1: proprietà x dell'espressione o
o.y.z                      // => 3: proprietà z dell'espressione o.y
o["x"]                     // => 1: proprietà x dell'oggetto o
a[1]                       // => 4: elemento all'indice 1 dell'espressione a
a[2]["1"]                  // => 6: elemento all'indice 1 dell'espressione a[2]
a[0].x                     // => 1: proprietà x dell'espressione a[0]

Con entrambi i tipi di espressione di accesso alle proprietà, l'espressione prima del . o [ viene prima valutata. Se il valore è null o undefined, l'espressione genera un TypeError, poiché questi sono i due valori JavaScript che non possono avere proprietà. Se l'espressione dell'oggetto è seguita da un punto e un identificatore, il valore della proprietà denominata da quell'identificatore viene cercato e diventa il valore complessivo dell'espressione. Se l'espressione dell'oggetto è seguita da un'altra espressione tra parentesi quadre, quella seconda espressione viene valutata e convertita in una stringa. Il valore complessivo dell'espressione è quindi il valore della proprietà denominata da quella stringa. In entrambi i casi, se la proprietà denominata non esiste, allora il valore dell'espressione di accesso alle proprietà è undefined.

La sintassi .identificatore è la più semplice delle due opzioni di accesso alle proprietà, ma notiamo che può essere utilizzata solo quando la proprietà a cui vogliamo accedere ha un nome che è un identificatore legale, e quando conosciamo il nome quando scriviamo il programma. Se il nome della proprietà include spazi o caratteri di punteggiatura, o quando è un numero (per gli array), dobbiamo utilizzare la notazione con parentesi quadre. Le parentesi quadre vengono utilizzate anche quando il nome della proprietà non è statico ma è esso stesso il risultato di un calcolo.

Accesso Condizionale alle Proprietà

ES2020 aggiunge due nuovi tipi di espressioni di accesso alle proprietà:

espressione ?. identificatore
espressione ?.[ espressione ]

In JavaScript, i valori null e undefined sono gli unici due valori che non hanno proprietà. In un'espressione di accesso alle proprietà regolare che usa . o [], si ottiene un TypeError se l'espressione a sinistra valuta a null o undefined. È possibile usare la sintassi ?. e ?.[] per proteggerci da errori di questo tipo.

Consideriamo l'espressione a?.b. Se a è null o undefined, allora l'espressione valuta a undefined senza alcun tentativo di accedere alla proprietà b. Se a è qualche altro valore, allora a?.b valuta a qualsiasi cosa a.b valuterebbe (e se a non ha una proprietà chiamata b, allora il valore sarà di nuovo undefined).

Questa forma di espressione di accesso alle proprietà è talvolta chiamata "concatenamento opzionale" perché funziona anche per espressioni di accesso alle proprietà "concatenate" più lunghe come questa:

let a = { b: null };
a.b?.c.d   // => undefined

a è un oggetto, quindi a.b è un'espressione di accesso alle proprietà valida. Ma il valore di a.b è null, quindi a.b.c lancerebbe un TypeError. Usando ?. invece di . evitiamo il TypeError, e a.b?.c valuta a undefined. Questo significa che (a.b?.c).d lancerà un TypeError, perché quell'espressione tenta di accedere a una proprietà del valore undefined. Ma---e questa è una parte molto importante del "concatenamento opzionale"---a.b?.c.d (senza le parentesi) semplicemente valuta a undefined e non lancia un errore. Questo perché l'accesso alle proprietà con ?. è "a corto circuito": se la sotto-espressione a sinistra di ?. valuta a null o undefined, allora l'intera espressione immediatamente valuta a undefined senza ulteriori tentativi di accesso alle proprietà.

Naturalmente, se a.b è un oggetto, e se quell'oggetto non ha una proprietà chiamata c, allora a.b?.c.d lancerà di nuovo un TypeError, e vorremo usare un altro accesso condizionale alle proprietà:

let a = { b: {} };
a.b?.c?.d  // => undefined

L'accesso condizionale alle proprietà è anche possibile usando ?.[] invece di []. Nell'espressione a?.[b][c], se il valore di a è null o undefined, allora l'intera espressione immediatamente valuta a undefined, e le sotto-espressioni b e c non vengono mai nemmeno valutate. Se una di quelle espressioni ha effetti collaterali, l'effetto collaterale non si verificherà se a non è definito:

let a;          // Ops, abbiamo dimenticato di inizializzare questa variabile!
let indice = 0;
try {
    a[indice++]; // Lancia TypeError
} catch(e) {
    indice       // => 1: l'incremento avviene prima che il TypeError venga lanciato
}
a?.[indice++]    // => undefined: perché a è undefined
indice           // => 1: non incrementato perché ?.[] va a corto circuito
a[indice++]      // !TypeError: non si può indicizzare undefined.

L'accesso condizionale alle proprietà con ?. e ?.[] è una delle funzionalità più nuove di JavaScript. All'inizio del 2020, questa nuova sintassi è stata introdotta nella maggior parte dei browser principali.