Operatorul ?
Operatorul ?., sau operatorul optional chaining, permite verificarea unui obiect și a proprietăților sau metodelor sale pentru null și undefined. Dacă obiectul sau proprietățile/metodele sale sunt definite, atunci se poate accesa proprietățile sau metodele acestuia:
const tom = null;
const bob = {name: "Bob"};
function printName(person){
console.log(person.name);
}
printName(tom); // Uncaught TypeError: Cannot read properties of null (reading "name")
printName(bob);
În acest caz, variabila tom este null, prin urmare, nu are proprietatea name. Prin urmare, atunci când acest obiect este transmis în funcția printName, vom primi o eroare. În astfel de situații, putem verifica obiectul pentru null și undefined înainte de a accesa proprietățile sale:
const tom = null;
const bob = {name: "Bob"};
function printName(person){
if(person !==null && person !==undefined) console.log(person.name);
}
printName(tom);
printName(bob); // Bob
De asemenea, putem simplifica verificarea:
function printName(person){
if(person) console.log(person.name);
}
Dacă variabila person este null sau undefined, atunci instrucțiunea if(person) va returna false. Cu toate acestea, operatorul ?. oferă o modalitate mai elegantă de rezolvare:
const tom = null;
const bob = {name: "Bob"};
function printName(person){
console.log(person?.name);
}
printName(tom); // undefined
printName(bob); // Bob
După numele obiectului, se specifică operatorul ?. - dacă valoarea nu este null sau undefined, atunci se face referire la proprietatea/metoda indicată după punct. Dacă valoarea este null/undefined, atunci nu se face referire la proprietatea/metoda, iar pe consolă vom vedea undefined.
Acest operator poate fi utilizat atât înaintea referirii la proprietăți, cât și înaintea apelurilor de metode ale obiectului:
const tom = undefined;
const bob = {
name: "Bob",
sayHi(){
console.log(`Salut! Sunt ${this.name}`);
}
};
console.log(tom?.name); // undefined
console.log(bob?.name); // Bob
tom?.sayHi(); // nu se execută
bob?.sayHi(); // Salut! Sunt Bob
În acest caz, referirea la proprietatea name și apelul metodei sayHi() se fac doar în cazul în care obiectele tom și bob nu sunt egale cu null/undefined.
Mai mult, poți verifica în continuare lanțul de apeluri pentru prezența proprietății sau metodei în obiect:
obj.val?.prop // verificarea proprietății
obj.arr?.[index] // verificarea array-ului
obj.func?.(args) // verificarea funcției
Verificarea proprietății
Un obiect poate fi definit, dar să nu aibă o anumită proprietate:
const tom = { name: "Tom"};
const bob = {
name: "Bob",
company: {
title: "Microsoft"
}
};
console.log(tom.company?.title); // undefined
console.log(bob.company?.title); // Microsoft
Similar, putem accesa proprietățile unui obiect folosind sintaxa de array:
const tom = { name: "Tom"};
const bob = {
name: "Bob",
company: {
title: "Microsoft"
}
};
console.log(tom.company?.["title"]); // undefined
console.log(bob.company?.["title"]); // Microsoft
Verificarea proprietății-array
Similar, putem verifica existența unei proprietăți-array înainte de a accesa elementele sale:
const tom = { name: "Tom"};
const bob = {
name: "Bob",
languages: ["javascript", "typescript"]
};
console.log(tom.languages?.[0]); // undefined
console.log(bob.languages?.[0]); // javascript
Verificarea metodei
Un obiect poate să nu aibă o metodă pe care o putem apela. Dacă metoda nu este definită, atunci când încercăm să apelăm o metodă nedefinită, vom întâmpina o eroare. În acest caz, de asemenea, putem verifica existența metodei:
const tom = { name: "Tom"};
const bob = {
name: "Bob",
say(words){
console.log(words);
}
};
console.log(tom.say?.("my name is Tom")); // undefined
console.log(bob.say?.("my name is Bob")); // my name is Bob
Lanț de verificări
Cu ajutorul operatorului ?. poți crea lanțuri de verificări, verificând în mod secvențial dacă valoarea este null/undefined:
const sam = {name: "Sam"};
const tom = {
name: "Tom",
company: { title: "Google"}
};
const bob = {
name: "Bob",
company: {
title: "Microsoft",
print(){
console.log(`Compania ${this.title}`)
}
}
};
sam?.company?.print?.(); // nu este apelat - nu există proprietatea company
tom?.company?.print?.(); // nu este apelat - nu există metoda print
bob?.company?.print?.(); // Compania Microsoft