When you access a deeply nested property in JavaScript, JavaScript gives an error like Cannot read property 'x' of undefined.
That's frustrating, right? 😖
Optional chaining (?.) solves this problem. It allows you to safely access deeply nested values without worrying about breaking your code when something in the chain is null or undefined.
What is Optional Chaining?
Optional chaining is a feature in JavaScript introduced in ES2020 that lets you access properties of an object without throwing an error, even if they are null or undefined.
Syntax:
object?.property;
object?.[expression];
object?.method?.();If the left-hand side is null or undefined, it short-circuits and returns undefined, instead of throwing an error.
Why Use Optional Chaining?
Before optional chaining, accessing deeply nested missing properties could crash your app.
const user = {};
console.log(user.address.country); // Error: Cannot read property 'country' of undefinedNow with optional chaining:
console.log(user.address?.country); // Output: undefinedExamples of Optional Chaining
Accessing a Nested Property
Without optional chaining:
const user = {
name: "Shefali",
address: {
country: "India",
},
};
console.log(user.address.country); // Output: India
console.log(user.profile.bio); // Uncaught TypeError: user.profile is undefinedWith optional chaining:
const user = {
name: "Shefali",
address: {
country: "India",
},
};
console.log(user.address?.country); // Output: India
console.log(user.profile?.bio); // Output: undefinedAccessing an Array Item Safely
Without optional chaining:
const users = null;
console.log(users[0]); // Uncaught TypeError: users is nullWith optional chaining:
const users = null;
console.log(users?.[0]); // Output: undefinedCalling a Method Safely
Without optional chaining:
const user = {
sayHi: () => console.log("Hello!"),
};
user.sayHi(); // Output: Hello!
user.sayBye(); // Uncaught TypeError: user.sayBye is not a functionWith optional chaining:
const user = {
sayHi: () => console.log("Hello!"),
};
user.sayHi?.(); // Output: Hello!
user.sayBye?.(); // Output: undefined (no error thrown)If the method doesn't exist, JavaScript won't throw an error, it just skips the call.
API Responses
Without optional chaining:
const apiResponse = {
data: {
user: {
profile: { name: "Shefali" },
},
},
};
console.log(apiResponse.data.user.profile.name); // Output: 'Shefali'
console.log(apiResponse.data.user.settings.theme); // Uncaught TypeError: apiResponse.data.user.settings is undefinedWith optional chaining:
const apiResponse = {
data: {
user: {
profile: { name: "Shefali" },
},
},
};
console.log(apiResponse.data?.user?.profile?.name); // Output: 'Shefali'
console.log(apiResponse.data?.user?.settings?.theme); // Output: undefinedOptional Chaining with Nullish Coalescing
You can combine optional chaining with the nullish coalescing ?? operator to provide a default value.
For example:
const user = {};
const bio = user.profile?.bio ?? "No bio available!";
console.log(bio); // Output: No bio available!If profile or bio doesn’t exist, it returns the fallback.
Things to Keep in Mind
- You can only use
?.on something that might benullorundefined. If the object exists but the property doesn’t, it still returnsundefined, and that's fine! - Don’t overuse it. Optional chaining is powerful, but you should still validate your data properly in most cases.
👉 Next tutorial: JavaScript Arrays