Оператор ?. или 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