Оператор ?. или optional chaning-оператор позволяет проверить объект и его свойства и методы на null и undefined, и если объект или его свойства/методы определены, то обратиться к
его свойствам или методам:
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);
В данном случае переменная tom равна null, соответственно у ней нет свойства name. Соответственно при передаче этого объекта в функцию
printName мы получим ошибку. В этом случае мы можем перед обращением к объекту проверять его на null и undefined:
const tom = null;
const bob = {name: "Bob"};
function printName(person){
if(person !==null && person !==undefined) console.log(person.name);
}
printName(tom);
printName(bob); // Bob
Также мы можем сократить проверку:
function printName(person){
if(person) console.log(person.name);
}
Если person равен null или undefined, то if(person) возвратит false.
Однако оператор ?. предлагает более элегантный способ решения:
const tom = null;
const bob = {name: "Bob"};
function printName(person){
console.log(person?.name);
}
printName(tom); // undefined
printName(bob); // Bob
После названия объекта указывается оператор ?. - если значение не равно null и undefined, то идет обращение к свойству/методу, которые указаны после точки.
Если же значени равно null/undefined, то обращения к свойству/методу не происходит. И на консоли мы увидим undefined.
Данный оператор можно использовать перед обращением как к свойствам, так и к методам объекта:
const tom = undefined;
const bob = {
name: "Bob",
sayHi(){
console.log(`Hi! I am ${this.name}`);
}
};
console.log(tom?.name); // undefined
console.log(bob?.name); // Bob
tom?.sayHi(); // не выполняется
bob?.sayHi(); // Hi! I am Bob
В данном случае обращение к свойству name и методу sayHi() происходит только в том случае, если объекты tom и bob не равны null/undefined.
Более того далее по цепочке вызывов проверять наличие свойства или метода в объекте.
obj.val?.prop // проверка свойства obj.arr?.[index] // провера массива obj.func?.(args) // проверка функции
Объект может быть определен, однако не иметь какого-то свойства:
const tom = { name: "Tom"};
const bob = {
name: "Bob",
company: {
title: "Microsoft"
}
};
console.log(tom.company?.title); // undefined
console.log(bob.company?.title); // Microsoft
Подобным образом мы можем обращаться к свойствам объекта с помощью синтаксиса массивов:
const tom = { name: "Tom"};
const bob = {
name: "Bob",
company: {
title: "Microsoft"
}
};
console.log(tom.company?.["title"]); // undefined
console.log(bob.company?.["title"]); // Microsoft
Аналогично мы можем проверять наличие свойства-массива перед обращением к его элементам:
const tom = { name: "Tom"};
const bob = {
name: "Bob",
languages: ["javascript", "typescript"]
};
console.log(tom.languages?.[0]); // undefined
console.log(bob.languages?.[0]); // javascript
Объект также может не иметь вызываемого у него метода. Если метод не определен, то при обращении к неопределенному методу мы столкнемся с ошибкой, и в этом случае также можно проверять наличие метода:
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
С помощью оператора ?. можно создавать цепочки проверок, последовательно проверяя, представляет ли значение null/undefined:
const sam = {name: "Sam"};
const tom = {
name: "Tom",
company: { title: "Google"}
};
const bob = {
name: "Bob",
company: {
title: "Microsoft",
print(){
console.log(`Компания ${this.title}`)
}
}
};
sam?.company?.print?.(); // не вызывается - нет свойства company
tom?.company?.print?.(); // не вызывается - нет метода print
bob?.company?.print?.(); // Компания Microsoft