Σε αντίθεση με πολλές άλλες γλώσσες, στη JavaScript υπάρχουν δύο διαφορετικές οντότητες που αντιπροσωπεύουν την απουσία μιας (ουσιαστικής) τιμής.
Υπάρχουν το null και το undefined.
Η πρωτόγονη τιμή null χρησιμοποιείται ως μια σκόπιμα "κενή τιμή" για μια μεταβλητή.
Σε άλλες γλώσσες, ένα παρόμοιο κατασκεύασμα μπορεί να χρησιμοποιείται μόνο για (απόντα) αντικείμενα ή τύπους δεικτών.
Στη JavaScript το null αντιπροσωπεύει γενικά μια κενή τιμή για οποιονδήποτε τύπο.
let name = null;
// name is intentionally set to "empty" because it is not
// available
Μπορείς να ελέγξεις αν μια μεταβλητή είναι null χρησιμοποιώντας τον τελεστή αυστηρής ισότητας ===.
Αν και το null είναι μια πρωτόγονη τιμή, ο typeof τελεστής επιστρέφει "λανθασμένα" object για ιστορικούς λόγους.
Αυτό σημαίνει ότι δεν μπορεί να χρησιμοποιηθεί από μόνο του για να ελέγξεις αν μια μεταβλητή είναι null.
let name = null;
name === null;
// => true
// Pitfall:
typeof name;
// => 'object'
Μια μεταβλητή στην οποία δεν έχει ανατεθεί τιμή είναι τύπου
undefined.1
Αυτό σημαίνει ότι ενώ το null αντιπροσωπεύει μια κενή τιμή (αλλά και πάλι μια τιμή), το undefined αντιπροσωπεύει την πλήρη απουσία μιας τιμής. 🤯
Το undefined εμφανίζεται σε διαφορετικά πλαίσια.
undefined.undefined.undefined.undefined, εκτός αν αυτό το όρισμα έχει προεπιλεγμένη τιμή.let name;
console.log(name);
// => undefined
let obj = { greeting: 'hello world' };
console.log(obj.missingKey);
// => undefined
function returnNothing() {
return;
}
console.log(returnNothing());
// => undefined
Μπορείς να ελέγξεις αν μια μεταβλητή είναι undefined χρησιμοποιώντας τον τελεστή αυστηρής ισότητας === ή τον τελεστή typeof.
let name;
name === undefined;
// => true
typeof name === 'undefined';
// => true
Δε συνιστάται να αναθέτεις χειροκίνητα undefined σε μια μεταβλητή, χρησιμοποίησε πάντα null αντ' αυτού, ώστε να είναι σαφές ότι έθεσες μια κενή τιμή σκόπιμα.
Όπως αναφέρθηκε παραπάνω, η πρόσβαση σε ένα ανύπαρκτο κλειδί ενός αντικειμένου επιστρέφει undefined στη JavaScript.
Ωστόσο, αν προσπαθήσεις να ανακτήσεις μια εμφωλευμένη τιμή και το γονικό κλειδί δεν υπάρχει, η αξιολόγηση του εμφωλευμένου κλειδιού εκτελείται πάνω σε undefined και οδηγεί σε TypeError: Cannot read property ... of undefined.
Θεωρητικά, θα έπρεπε πάντα να ελέγχεις ότι το γονικό κλειδί υπάρχει πριν προσπαθήσεις να ανακτήσεις το εμφωλευμένο κλειδί.
Αυτό γινόταν συχνά με τον τελεστή AND &&, αλλά για βαθιά εμφωλευμένες τιμές οδηγεί σε πολύ μακροσκελείς εκφράσεις.
obj.level1 && obj.level1.level2 && obj.level1.level2.level3;
Για να λυθεί αυτό το πρόβλημα, η προαιρετική αλυσίδωση προστέθηκε στην προδιαγραφή της γλώσσας το 2020.
Με τον τελεστή προαιρετικής αλυσίδωσης ?. μπορείς να διασφαλίσεις ότι η JavaScript θα προσπαθήσει να προσπελάσει το εμφωλευμένο κλειδί μόνο αν ο γονέας δεν ήταν null ή undefined.
Διαφορετικά, επιστρέφεται 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
Υπάρχουν περιπτώσεις όπου θέλεις να εφαρμόσεις μια προεπιλεγμένη τιμή σε περίπτωση που μια μεταβλητή είναι null ή undefined.
Στο παρελθόν, αυτό γινόταν συχνά με τον τριαδικό τελεστή ? ή αξιοποιώντας την οκνηρή αξιολόγηση του τελεστή OR ||.
Αυτό έχει το μειονέκτημα ότι η προεπιλεγμένη τιμή εφαρμόζεται σε όλες τις περιπτώσεις όπου η μεταβλητή είναι falsy (π.χ. '' ή 0), όχι μόνο όταν είναι null ή undefined.
Αυτό μπορεί εύκολα να προκαλέσει απροσδόκητα αποτελέσματα.
let amount = null;
amount = amount || 1;
// => 1
amount = 0;
amount = amount || 1;
// => 1
amount = 0;
amount ? amount : 1;
// => 1
Για να αντιμετωπιστεί αυτό, εισήχθη ο τελεστής συνένωσης nullish ??.
Όπως ακριβώς η προαιρετική αλυσίδωση, προστέθηκε στην προδιαγραφή της γλώσσας το 2020.
Ο τελεστής συνένωσης nullish ?? επιστρέφει τον δεξιό τελεστέο μόνο όταν ο αριστερός τελεστέος είναι null ή undefined.
Διαφορετικά, επιστρέφεται ο αριστερός τελεστέος.
Έτσι, μια προεπιλεγμένη τιμή μπορεί πλέον να εφαρμοστεί πιο στοχευμένα.
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 (πρόσβαση στις 4 Ιουνίου 2021).