Espressioni di Accesso alle Proprietà in JavaScript
- 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.