operator ?. or optional chaning-operator allows you to check the object and its properties and methods for null and undefined, and if the object or its properties/methods are defined, then access its properties or methods:
let volume = null; let bob = {name: "Bob"}; function printName(person){ console.log(person.name); } printName(tom); // Uncaught TypeError: Cannot read properties of null (reading "name") printName(bob);
In this case, the variable tom is null, so it does not have the property name. Accordingly, when passing this object to a function printName, we will get an error. In this case, we can check for null and undefined before accessing the object:
let volume = null; let bob = {name: "Bob"}; function printName(person){ if(person !==null && person !==undefined) console.log(person.name); } printName(tom); printName(bob); // Bob
We can also shorten the check:
function printName(person){ if(person) console.log(person.name); }
If person is null or undefined, it will if(person) return false.
However, the ?. offers a more elegant solution:
let volume = null; let bob = {name: "Bob"}; function printName(person){ console.log(person?.name); } printName(tom); // undefined printName(bob); // Bob
An operator is indicated after the name of the object ?.- if the value is not equal to nulland undefined, then the property/method specified after the dot is accessed. If the value is null/undefined, then the property/method is not accessed. And on the console we will see undefined.
This operator can be used before accessing both properties and methods of an object:
let tom = undefined; let bob = { name: "Bob", sayHi(){ console.log(`Hi! I am ${this.name}`); } }; console.log(tom?.name); // undefined console.log(bob?.name); // Bob tom?.sayHi(); // not executed bob?.sayHi(); // Hi! I am Bob
name In this case, the property and method are accessed sayHi()only if the objects tom and bob are not null/undefined.
Moreover, further down the chain of calls, check for the presence of a property or method in an object.
obj.val?.prop // property check obj.arr?.[index] // check array obj.func?.(args) // function check
Property check
An object can be defined but not have a property:
let tom = { name: "Tom"}; let bob = { name: "Bob", company: { title: "Microsoft" } }; console.log(tom.company?.title); // undefined console.log(bob.company?.title); // Microsoft
Similarly, we can access the properties of an object using the array syntax:
let tom = { name: "Tom"}; let bob = { name: "Bob", company: { title: "Microsoft" } }; console.log(tom.company?.["title"]); // undefined console.log(bob.company?.["title"]); // Microsoft
Checking an Array Property
Similarly, we can check for the existence of an array property before accessing its elements:
let tom = { name: "Tom"}; let bob = { name: "Bob", languages: ["javascript", "typescript"] }; console.log(tom.languages?.[0]); // undefined console.log(bob.languages?.[0]); // javascript
Method Check
An object may also not have a method called on it. If the method is not defined, then when accessing the undefined method, we will encounter an error, in which case we can also check for the presence of the method:
let tom = { name: "Tom"}; let 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
Chain of checks
With the ? operator. you can create chains of checks by successively checking whether a value represents null/undefined:
</pre> let sam = {name: "Sam"}; let tom = { name: "Tom", company: {title: "Google"} }; let bob = { name: "Bob", company: { title: "Microsoft", print(){ console.log(`Company ${this.title}`) } } }; sam?.company?.print?.(); // not called - no company property tom?.company?.print?.(); // not called - no print method bob?.company?.print?.(); // Microsoft company <pre>