Sok más nyelvvel ellentétben a JavaScriptben két különböző dolog is jelöli egy (értelmes) érték hiányát.
Ez a null és az undefined.
A null primitív érték arra való, hogy egy változó szándékosan „üres értéket” kapjon.
Más nyelvekben hasonló konstrukciót talán csak (hiányzó) objektumokra vagy mutatótípusokra használnak.
A JavaScriptben a null általában bármely típusnál üres értéket jelöl.
let name = null;
// name is intentionally set to "empty" because it is not
// available
Azt, hogy egy változó értéke null, a szigorú egyenlőség operátor (===) segítségével ellenőrizheted.
Bár a null primitív érték, a typeof operátor „tévesen” object-et ad vissza történelmi okokból.
Ez azt jelenti, hogy önmagában nem használható annak ellenőrzésére, hogy egy változó értéke null-e.
let name = null;
name === null;
// => true
// Pitfall:
typeof name;
// => 'object'
Ha egy változóhoz nem rendeltünk értéket, annak a típusa
undefined.1
Ez azt jelenti, hogy míg a null egy üres értéket jelöl (de mégiscsak érték), addig az undefined egy érték teljes hiányát jelöli. 🤯
Az undefined többféle helyzetben is megjelenik.
undefined lesz.undefined-et kapsz.undefined.undefined lesz, kivéve, ha az argumentumnak van alapértelmezett értéke.let name;
console.log(name);
// => undefined
let obj = { greeting: 'hello world' };
console.log(obj.missingKey);
// => undefined
function returnNothing() {
return;
}
console.log(returnNothing());
// => undefined
Azt, hogy egy változó értéke undefined, a szigorú egyenlőség operátorral (===) vagy a typeof operátorral ellenőrizheted.
let name;
name === undefined;
// => true
typeof name === 'undefined';
// => true
Nem ajánlott kézzel undefined-et rendelni egy változóhoz; helyette mindig a null-t használd, hogy egyértelmű legyen: szándékosan állítottál be üres értéket.
Ahogy fentebb említettük, ha egy objektumban egy nem létező kulcshoz férünk hozzá, az a JavaScriptben undefined-et ad vissza.
Ha viszont egy egymásba ágyazott értéket próbálsz lekérni, és a szülő kulcs nem létezik, akkor a beágyazott kulcs kiértékelése az undefined-en történik, és a TypeError: Cannot read property ... of undefined hibához vezet.
Elméletileg mindig ellenőrizni kellene, hogy létezik-e a szülő kulcs, mielőtt lekérnéd a beágyazott kulcsot.
Ezt gyakran az és operátorral (&&) oldották meg, de a mélyen egymásba ágyazott értékeknél ez nagyon hosszú kifejezésekhez vezet.
obj.level1 && obj.level1.level2 && obj.level1.level2.level3;
Ennek a problémának a megoldására 2020-ban bekerült a nyelvi specifikációba az opcionális láncolás.
Az opcionális láncolás operátorral (?.) elérheted, hogy a JavaScript csak akkor próbálja meg elérni a beágyazott kulcsot, ha a szülő nem null vagy undefined.
Ellenkező esetben undefined-et ad vissza.
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
Vannak helyzetek, amikor alapértelmezett értéket szeretnél adni arra az esetre, ha egy változó null vagy undefined.
Korábban ezt gyakran a feltételes operátorral (?) oldották meg, vagy a vagy operátor (||) lusta kiértékelését kihasználva.
Ennek az a hátránya, hogy az alapértelmezett érték minden olyan esetben érvénybe lép, amikor a változó hamis értékű (például '' vagy 0), nem csak akkor, amikor null vagy undefined.
Ez könnyen váratlan eredményekhez vezethet.
let amount = null;
amount = amount || 1;
// => 1
amount = 0;
amount = amount || 1;
// => 1
amount = 0;
amount ? amount : 1;
// => 1
Ennek megoldására vezették be a nullish coalescing operátort (??).
Az opcionális láncoláshoz hasonlóan ez is 2020-ban került be a nyelvi specifikációba.
A nullish coalescing operátor (??) csak akkor adja vissza a jobb oldali operandust, ha a bal oldali operandus null vagy undefined.
Ellenkező esetben a bal oldali operandust adja vissza.
Így most már pontosabban lehet alapértelmezett értéket adni.
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 (megtekintve: 2021. június 4.).