JavaScript - Optional Chaining

Hello there, future JavaScript wizards! ? Today, we're going to embark on an exciting journey into the world of Optional Chaining. Don't worry if you're new to programming – I'll be your friendly guide, and we'll take this step-by-step. By the end of this lesson, you'll be chaining like a pro! Let's dive in!

JavaScript - Optional Chaining

The Non-existing Property Problem

Imagine you're trying to find a book in a massive library. You know it's supposed to be in the "Science Fiction" section, on the third floor, in the back corner. But what if the library doesn't even have a third floor? Or what if there's no "Science Fiction" section? That's the kind of problem we often face in JavaScript when dealing with nested objects.

Let's look at an example:

const library = {
  fiction: {
    fantasy: {
      books: ['The Hobbit', 'Harry Potter']
    }
  }
};

console.log(library.fiction.sciFi.books);

If you run this code, you'll get an error: "Cannot read property 'books' of undefined". Why? Because library.fiction.sciFi doesn't exist! This is where Optional Chaining comes to the rescue.

What is Optional Chaining in JavaScript?

Optional Chaining is like a safety net for your code. It allows you to access nested object properties without worrying if the intermediate properties exist. It's denoted by the ?. operator.

Let's rewrite our previous example with Optional Chaining:

const library = {
  fiction: {
    fantasy: {
      books: ['The Hobbit', 'Harry Potter']
    }
  }
};

console.log(library.fiction.sciFi?.books);

Now, instead of throwing an error, this will simply return undefined. It's like asking, "If sciFi exists, can you please give me its books? If not, no worries!"

Optional Chaining with Function Calls

Optional Chaining isn't just for object properties. You can use it with function calls too! Let's say we have a library system where books can be checked out:

const library = {
  fiction: {
    fantasy: {
      checkOut: function(book) {
        console.log(`Checking out ${book}`);
      }
    }
  }
};

library.fiction.fantasy.checkOut?.('The Hobbit');
library.fiction.sciFi?.checkOut?.('Dune');

In this example, 'The Hobbit' will be checked out, but nothing will happen with 'Dune' because sciFi doesn't exist. No errors, just smooth sailing!

Optional Chaining with Expression

You can also use Optional Chaining with square bracket notation. This is useful when your property names are dynamic or contain special characters:

const users = {
  '123': { name: 'Alice', age: 30 },
  '456': { name: 'Bob', age: 25 }
};

const userId = '789';
console.log(users[userId]?.name);

This will return undefined because there's no user with ID '789', but it won't throw an error.

Optional Chaining with the "delete" Operator

The delete operator can also be used with Optional Chaining. This is handy when you want to delete a property that might not exist:

const obj = {
  prop: {
    innerProp: 'value'
  }
};

delete obj.prop?.innerProp;
delete obj.nonExistent?.prop;

The first delete will work as expected, removing innerProp. The second one will do nothing, but won't throw an error.

Short-circuiting with Optional Chaining

Optional Chaining has a neat feature called short-circuiting. If the left part of the ?. is null or undefined, the evaluation stops and returns undefined:

const obj = null;
console.log(obj?.prop?.subProp);  // Returns undefined

This is super helpful for avoiding those pesky "Cannot read property of null" errors!

Nullish Coalescing Operator with Optional Chaining

The Nullish Coalescing Operator (??) works great with Optional Chaining. It allows you to provide a default value if the result of the Optional Chaining is null or undefined:

const user = {
  name: 'Alice',
  details: {
    age: 30
  }
};

console.log(user.details?.job ?? 'unemployed');  // Returns 'unemployed'
console.log(user.details?.age ?? 'unknown');     // Returns 30

This is perfect for providing fallback values when properties might not exist.

Here's a table summarizing the methods we've covered:

Method Syntax Description
Property Access obj?.prop Safely access nested object properties
Function Call func?.() Safely call a function that might not exist
Expression obj?.[expr] Safely access properties with dynamic or special names
Delete Operator delete obj?.prop Safely delete a property that might not exist
Short-circuiting obj?.prop?.subProp Stops evaluation if any part is null or undefined
With Nullish Coalescing obj?.prop ?? defaultValue Provide a fallback for null or undefined results

And there you have it, folks! You've just leveled up your JavaScript skills with Optional Chaining. Remember, coding is like building with LEGO – start with the basics, and before you know it, you'll be creating masterpieces. Keep practicing, stay curious, and happy coding! ??‍??‍?

Credits: Image by storyset