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