Door 07 | JS Adventskalender
Skip to content

Door 07

Published: at 07:00 AMSuggest Changes

Optional Chaining – Safely Accessing Nested Objects

In a JavaScript developer’s daily work, accessing deeply nested objects and arrays is a common task. But what happens when certain levels of these structures are not defined? Without appropriate checks, the code can quickly run into errors. With the introduction of the Optional Chaining Operator (?.) in ES2020, JavaScript now offers an elegant solution to this problem.

The Problem with Nested Structures

Consider an example:

const user = {
  name: 'Alex',
  address: {
    city: 'Berlin',
    postalCode: '10115'
  }
};

console.log(user.address.city); // 'Berlin'

This works perfectly as long as user and address are defined. But what happens when address is missing?

const user = {
  name: 'Alex'
};

console.log(user.address.city); // TypeError: Cannot read property 'city' of undefined

To avoid this error, we previously had to implement extensive checks:

const user = {
  name: 'Alex'
};

if (user && user.address && user.address.city) {
  console.log(user.address.city);
} else {
  console.log('City not available');
}

Introduction to Optional Chaining

The Optional Chaining Operator ?. significantly simplifies these checks. It allows you to make access to nested properties safe without having to check each time whether each level is defined.

Syntax:

object?.property
object?.[expression]
object?.method()

If the part before ?. is null or undefined, the expression is immediately evaluated as undefined without throwing an error.

Examples of Application

1. Access to Properties:

const user = {
  name: 'Alex'
};

console.log(user.address?.city); // undefined

Instead of throwing an error when address is not defined, the expression simply returns undefined.

2. Access to Array Elements:

const users = null;

console.log(users?.[0]); // undefined

If users is null or undefined, access to the first element is not executed and undefined is returned.

3. Calling Methods:

const user = {
  name: 'Alex',
  greet() {
    return 'Hello';
  }
};

console.log(user.greet?.()); // 'Hello'

const userWithoutGreet = {
  name: 'Ben'
};

console.log(userWithoutGreet.greet?.()); // undefined

If the method greet does not exist, the call is not executed and undefined is returned.

Combination with the Nullish Coalescing Operator

Often you want to use a default value when access returns undefined. This is where the Nullish Coalescing Operator ?? comes into play.

Example:

const user = {};

const city = user.address?.city ?? 'City not available';

console.log(city); // 'City not available'

If user.address?.city is undefined, 'City not available' is used as the default value.

Caution When Using

Practical Use Cases

1. Working with API Data:

With data coming from external APIs, it is often unclear whether certain fields are present.

fetch('https://api.example.com/user/123')
  .then(response => response.json())
  .then(data => {
    console.log(data.profile?.email ?? 'Email not available');
  });

2. Event Handling in the Browser:

element.addEventListener('click', (event) => {
  const button = event.target?.dataset?.button;
  if (button) {
    // Action based on the button dataset
  }
});

Comparison with Traditional Methods

Compared to the traditional method, this notation is much easier to read and write. After all, we write code for ourselves and not for the machine.

Without Optional Chaining:

if (object && object.property && object.property.subProperty) {
  // Access subProperty
}

With Optional Chaining:

if (object?.property?.subProperty) {
  // Access subProperty
}

The code becomes not only shorter but also more readable.

Conclusion

The Optional Chaining Operator ?. is a valuable tool in modern JavaScript applications. It reduces the effort for null and undefined checks and makes the code cleaner and more maintainable. Especially when dealing with complex or uncertain data structures, it offers an elegant solution to avoid errors.

Use Optional Chaining in your next project and experience how it facilitates working with nested objects!


Previous Post
Door 08
Next Post
Door 06