🧩 1. What Is Optional Chaining?
Optional chaining (?.) lets you safely access nested object properties
without causing an error if something in the chain is null or undefined.
👉 It returns undefined instead of throwing an error.
🧱 The Problem (Without Optional Chaining)
const user = {};
console.log(user.profile.name); // ❌ TypeError: Cannot read properties of undefined
Here, user.profile is undefined,
so trying to access .name crashes the code.
✅ The Solution (With Optional Chaining)
const user = {};
console.log(user.profile?.name); // ✅ undefined (no error)
If profile doesn’t exist, the expression simply stops and returns undefined.
🧠 2. Basic Syntax
object?.property
object?.[key]
object?.method?.()
You can use it with:
- Object properties
 - Dynamic keys
 - Methods/functions
 
🧩 Example 1 — Object Property
const user = { info: { name: "Alice" } };
console.log(user.info?.name);     // "Alice"
console.log(user.profile?.name);  // undefined (no error)
🧩 Example 2 — Array Index or Dynamic Key
const data = { items: ["A", "B"] };
console.log(data.items?.[0]);   // "A"
console.log(data.other?.[0]);   // undefined
🧩 Example 3 — Method Calls
const user = {
  greet() {
    return "Hello!";
  },
};
console.log(user.greet?.());      // "Hello!"
console.log(user.sayBye?.());     // undefined (no crash)
🧩 Example 4 — Nested Access
Without optional chaining:
const city = user && user.address && user.address.city;
With optional chaining:
const city = user?.address?.city;
✅ Much cleaner and more readable.
⚡ 3. Combining with Nullish Coalescing (??)
You can combine ?. with ?? (another ES2020 feature)
to provide default values when something is missing.
const user = {};
const city = user?.address?.city ?? "Unknown";
console.log(city); // "Unknown"
✅ Returns "Unknown" instead of crashing or showing undefined.
🧩 4. Real-World Example
Example: API Response
const response = {
  user: {
    profile: { name: "Sarah" },
  },
};
// Traditional way (unsafe)
console.log(response.user.profile.name); // Works
// console.log(response.account.details.id); // ❌ crash
// Safe way
console.log(response.account?.details?.id); // ✅ undefined
✅ Helps when working with APIs or user input where data may be missing.
🚨 5. What It Can’t Do
❌ You can’t use it on the left-hand side of an assignment:
user?.name = "Alice"; // SyntaxError ❌
❌ It only checks for null or undefined, not falsy values like 0 or "".
🧠 6. Quick Comparison
| Without Optional Chaining | With Optional Chaining | 
|---|---|
user && user.address && user.address.city | user?.address?.city | 
data && data.items && data.items[0] | data?.items?.[0] | 
obj && obj.method && obj.method() | obj.method?.() | 
✨ 7. Summary
| Concept | Description | Example | Result | 
|---|---|---|---|
?. | Safe property access | user?.name | Returns undefined if missing | 
?.[] | Safe dynamic key access | user?.[key] | Returns undefined if missing | 
?.() | Safe method call | user.method?.() | Calls only if method exists | 
💡 8. Practical Tip
Optional chaining is best for:
- API responses with optional fields
 - Deeply nested data (e.g., 
user?.profile?.settings?.theme) - Avoiding repetitive 
ifor&&checks 
