A differenza di molti altri linguaggi, in JavaScript ci sono due entità diverse che rappresentano l'assenza di un valore (significativo).
Ci sono null e undefined.
Il valore primitivo null viene usato come «valore vuoto» intenzionale per una variabile.
In altri linguaggi, una costruzione simile potrebbe essere usata solo per oggetti (mancanti) o per tipi puntatore.
In JavaScript null rappresenta in generale un valore vuoto per qualsiasi tipo.
let name = null;
// name is intentionally set to "empty" because it is not
// available
Puoi verificare se una variabile è null usando l'operatore di uguaglianza stretta ===.
Anche se null è un valore primitivo, l'operatore typeof restituisce «erroneamente» object, per motivi storici.
Questo significa che non può essere usato da solo per verificare se una variabile è null.
let name = null;
name === null;
// => true
// Pitfall:
typeof name;
// => 'object'
A variable that has not been assigned a value is of type
undefined.1
Questo significa che mentre null rappresenta un valore vuoto (ma pur sempre un valore), undefined rappresenta l'assenza totale di un valore. 🤯
undefined compare in contesti diversi.
undefined.undefined.undefined.undefined, a meno che quell'argomento non abbia un valore predefinito.let name;
console.log(name);
// => undefined
let obj = { greeting: 'hello world' };
console.log(obj.missingKey);
// => undefined
function returnNothing() {
return;
}
console.log(returnNothing());
// => undefined
Puoi verificare se una variabile è undefined usando l'operatore di uguaglianza stretta === oppure l'operatore typeof.
let name;
name === undefined;
// => true
typeof name === 'undefined';
// => true
Non è consigliabile assegnare manualmente undefined a una variabile: al suo posto usa sempre null, così è chiaro che hai impostato intenzionalmente un valore vuoto.
Come accennato in precedenza, accedere a una chiave inesistente in un oggetto restituisce undefined in JavaScript.
Tuttavia, se provi a recuperare un valore annidato e la chiave padre non esiste, la valutazione della chiave annidata viene eseguita su undefined e porta a TypeError: Cannot read property ... of undefined.
In teoria, dovresti sempre controllare che la chiave padre esista prima di poter provare a recuperare la chiave annidata.
Spesso lo si faceva con l'operatore AND &&, ma per valori profondamente annidati questo porta a espressioni molto lunghe.
obj.level1 && obj.level1.level2 && obj.level1.level2.level3;
Per risolvere questo problema, nel 2020 è stato aggiunto alla specifica del linguaggio il concatenamento opzionale.
Con l'operatore di concatenamento opzionale ?. puoi assicurarti che JavaScript provi ad accedere alla chiave annidata solo se il padre non era null o undefined.
Altrimenti viene restituito undefined.
const obj = {
address: {
street: 'Trincomalee Highway',
city: 'Batticaloa',
},
};
obj.residence;
// => undefined
obj.address.zipCode;
// => undefined
obj.residence.street;
// => TypeError: Cannot read property 'street' of undefined
obj.residence?.street;
// => undefined
obj.residence?.street?.number;
// => undefined
Ci sono situazioni in cui vuoi applicare un valore predefinito nel caso in cui una variabile sia null o undefined.
In passato questo veniva spesso fatto con un operatore ternario ? oppure sfruttando la valutazione pigra dell'operatore OR ||.
Questo ha lo svantaggio che il valore predefinito viene applicato in tutti i casi in cui la variabile è falsy (ad esempio '' o 0), non solo quando è null o undefined.
Il che può facilmente causare risultati imprevisti.
let amount = null;
amount = amount || 1;
// => 1
amount = 0;
amount = amount || 1;
// => 1
amount = 0;
amount ? amount : 1;
// => 1
Per risolvere questo problema, è stato introdotto l'operatore di coalescenza nullish ??.
Proprio come il concatenamento opzionale, è stato aggiunto alla specifica del linguaggio nel 2020.
L'operatore di coalescenza nullish ?? restituisce l'operando di destra solo quando l'operando di sinistra è null o undefined.
Altrimenti viene restituito l'operando di sinistra.
Così ora un valore predefinito può essere applicato in modo più specifico.
let amount = null;
amount = amount ?? 1;
// => 1
amount = 0;
amount = amount ?? 1;
// => 0
[1] Undefined, MDN. (2021). https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined (consultato il 4 giugno 2021).