Come verificare se un oggetto possiede una proprietà in Javascript
Nelle lezioni precedenti abbiamo visto che gli oggetti Javascript sono aggregati o insiemi di proprietà. In questa lezione vediamo come sia possibile verificare la presenza o meno di una proprietà in un oggetto Javascript.
- Esistono tre tecniche per verificare se un oggetto possiede una proprietà: l'operatore
in, il metodohasOwnPropertye l'accesso diretto alla proprietà. - L'operatore
inverifica se una proprietà è presente nell'oggetto o in uno dei suoi prototipi. - Il metodo
hasOwnPropertyverifica se una proprietà è una own property, ovvero se è definita direttamente nell'oggetto e non in uno dei suoi prototipi. - L'accesso diretto alla proprietà può essere utilizzato per verificare se una proprietà esiste, ma non distingue tra una proprietà non definita e una proprietà impostata a
undefined.
Operatore in
Verificare la presenza di una proprietà è spesso una necessità molto utile che si presenta nello sviluppo dei programmi.
Il metodo più semplice di verifica è utilizzare l'operatore in. Vediamo un esempio:
1 2 3 4 5 6 7 8 9 10 | |
in prevede due operandi: una stringa che identifica la proprietà e l'oggetto in cui cercarla. Restituisce false se la proprietà non è presente, mentre restituisce true se essa è una proprietà dell'oggetto o di uno dei prototipi della sua catena.
Metodo hasOwnProperty
La seconda tecnica di verifica consiste nell'utilizzo del metodo hasOwnProperty.
Questo metodo, in realtà, è un metodo dell'oggetto Object e, pertanto, viene ereditato da quasi tutti gli oggetti (a meno che il loro prototipo non è null). Infatti, come abbiamo visto nella lezione relativa alla creazione degli oggetti, quasi tutti gli oggetti hanno come prototipo l'oggetto Object.
Attraverso questo metodo, che richiede come parametro una stringa contenente il nome della proprietà da ricercare, è possibile verificare la presenza o l'assenza di una proprietà. La differenza rispetto all'operatore in, tuttavia, è che questo metodo restituisce true solo per le own properties (come era intuibile dal nome). Vediamo, infatti, l'esempio:
1 2 3 4 5 6 7 8 9 10 | |
Metodo propertyIsEnumerable
Analogamente al metodo hasOwnProperty esiste anche il metodo propertyIsEnumerable che viene ereditato sempre da Object. Il suo funzionamento è identico a hasOwnProperty, l'unica differenza consiste nel fatto che restituisce false se la own property non è enumerable. Per capire cosa sia una proprietà numerabile o enumerable rimandiamo alla prossima lezione. In generale tutte le proprietà sono enumerabili a meno che non si utilizzino le metaclassi, ma questo è un argomento delle prossime lezioni. Per questo motivo, per il momento, possiamo considerare i due metodi, hasOwnProperty e propertyIsEnumerable, sostanzialmente identici.
Accesso diretto
La tecnica finale per verificare l'esistenza o meno di una proprietà è il semplice accesso diretto. Anzichè richiederne l'esistenza, si può richiedere direttamente la proprietà e verificare che essa sia diversa da undefined. Vediamo un esempio:
1 2 3 4 5 6 7 8 9 10 | |
Vi è una sottile differenza tra questa tecnica e l'operatore in. Utilizzando l'operatore in è in grado di distinguere tra l'esistenza di una proprietà che è stata impostata a undefined ed una proprietà che non esiste. Vediamo l'esempio:
1 2 3 4 5 6 7 8 | |
Errori di accesso alle proprietà
In generale, accedere ad una proprietà di un oggetto che non esiste (come abbiamo fatto sopra) non è un errore:
1 2 3 4 5 6 | |
Nell'esempio di sopra, la variabile result varrà undefined in quanto abbiamo provato ad accedere alla proprietà y di A, ma questa proprietà non esiste. L'interprete non lancerà eccezioni ma, anzi, l'esecuzione proseguirà come se nulla fosse accaduto.
Anche se a prima vista questo comportamento dell'interprete sembra strano o contraddittorio (in altri linguaggi verrebbe generata un'eccezione), esso è voluto. Ricordiamo, infatti, che gli oggetti in Javascript sono dinamici. Le proprietà possono essere aggiunge, rimosse e modificate a runtime. Pertanto, inserire un meccanismo di controllo che, ad ogni accesso in lettura, verifica l'esistenza o meno di una proprietà rallenterebbe in maniera considerevole l'esecuzione. Per questo motivo, i progettisti dello standard Javascript hanno optato per questo comportamento.
Ovviamente bisogna fare attenzione. Infatti, nel caso di sopra, non si presentano particolari problemi. Ma se la proprietà dell'oggetto fosse a sua volta un oggetto? Proviamo con un esempio:
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
In questo esempio abbiamo l'oggetto composto A di cui richiediamo la proprietà y per poi richiedere la proprietà z. Poiché effettivamente A possiede una proprietà y nessuna eccezione viene lanciata. Nel caso di B, invece, dato che richiederne la proprietà y restituisce undefined, nel momento in cui richiediamo z un'eccezione viene lanciata. Infatti è un errore in Javascript richiedere una proprietà di undefined.
Potremmo risolvere il problema in questo modo:
1 2 3 4 | |
Tuttavia è una soluzione prolissa e prona agli errori. Un modo più semplice per risolvere il problema è scrivere la seguente riga:
let result2 = B.y && B.y.z;
A prima vista, questa riga di codice può sembrare criptica. Ma ricordando come funzionano gli operatori booleani in Javascript, si può capire perché funziona. Infatti:
- Gli operatori booleani in Javascript sono cortocircuitati. Ciò significa che in questo caso in cui abbiamo l'operatore
&&(and) se il primo operando è falso, l'interprete non valuterà il secondo in quanto è inutile. Per questo seB.yèundefined(che in Javascript è assimilabile afalse), il secondo operandoB.y.znon verrà valutato e non verrà generata un'eccezione. Inoltre, dato che in Javascript qualsiasi valore può essere considerato un booleano, quando l'operatore di sinistra di&&è assimilabile afalse, ne verrà restituito il risultato che, nel nostro caso, èundefined. - Viceversa, se il primo operando è assimilabile a
true, come ad esempio seBavesse effettivamente una proprietày, allora, in tal caso, verrebbe valutato il secondo operando e restituito il risultato. Per cui, seB.y.zfosseundefinedotterremmo undefined, mentre se fosse diverso ne otterremmo il valore.
ECMAScript 2020 introduce un nuovo operatore: ?. che prende il nome di operatore di accesso condizionale. Utilizzando tale operatore possiamo riscrivere la riga di sopra, in maniera ancora più sintetica, come:
let result2 = B?.y?.z;
Riassumendo
In questa lezione abbiamo visto come verificare l'esistenza di una proprietà di un oggetto attraverso l'operatore in e i due metodi hasOwnProperty e propertyIsEnumerable. Inoltre abbiamo visto come, attraverso l'accesso diretto, sia possibile effettuare questa verifica. Sempre nel caso dell'accesso diretto abbiamo visto come usare gli operatori booleani cortocircuitati e l'operatore di accesso condizionale.
Nella prossima lezione vedremo il concetto di proprietà enumerabili e come enumerare o elencare tutte le proprietà di un oggetto.