Optional Chaining is a modern JavaScript feature (ES2020) that provides a safe way to access deeply nested properties of an object. It prevents errors by returning undefined
if a reference in the chain is null
or undefined
, thus avoiding the need for multiple conditional checks.
Example 1: Basic Property Access
const user = {
name: 'John Doe',
address: {
street: '123 Main St',
city: 'Anytown'
}
};
// Accessing a deeply nested property using Optional Chaining
const street = user.address?.street;
console.log(street); // Output: 123 Main St
// Trying to access a property on a nullish reference
const zipCode = user.location?.zipCode;
console.log(zipCode); // Output: undefined
Explanation
The code safely accesses user.address.street
. When trying to access user.location.zipCode
, it doesn't throw an error because user.location
is undefined
; instead, it short-circuits and returns undefined
.
Example 2: With Nullish Coalescing Operator (??
)
const settings = {
userPreferences: null
};
// Using Optional Chaining with the Nullish Coalescing Operator
const theme = settings.userPreferences?.theme ?? 'dark';
console.log(theme); // Output: dark
Explanation
This example attempts to get the theme
from userPreferences
. Since userPreferences
is null
, the Optional Chaining ?.
results in undefined
, and the Nullish Coalescing Operator ??
provides a default value of 'dark'.
Example 3: Optional Chaining with Function Calls
const apiClient = {
fetchData: () => 'Data fetched successfully!',
// processData method is not defined
};
// Safely calling a method that may not exist
const result = apiClient.processData?.();
console.log(result); // Output: undefined
Explanation
Optional Chaining can also be used for function calls. Here, apiClient.processData
is undefined
, so the ?.()
prevents a "not a function" TypeError and gracefully returns undefined
.
Example 4: Accessing Array Elements
const data = {
items: ['apple', 'banana']
};
// Safely accessing an array element
const firstItem = data.items?.[0];
console.log(firstItem); // Output: apple
// Attempting to access an element from a non-existent array
const userList = {
// users array is missing
};
const firstUser = userList.users?.[0];
console.log(firstUser); // Output: undefined
Explanation
This demonstrates using Optional Chaining to safely access an element by its index in an array. If the array itself (userList.users
) is null
or undefined
, the expression evaluates to undefined
without an error.
Example 5: Chaining Multiple Operators
const school = {
principal: {
name: 'Ms. Smith',
assistant: null // The assistant property is null
}
};
// Chaining multiple optional operators
const assistantName = school.principal?.assistant?.name;
console.log(assistantName); // Output: undefined
Explanation
Here, we chain multiple ?.
operators. The expression school.principal?.assistant
evaluates to null
. The chain stops, and the final result is undefined
without trying to access .name
on null
.
Example 6: Combining with Bracket Notation
const dynamicProperties = {
user: {
'first-name': 'Jane'
}
};
const propertyName = 'first-name';
// Using bracket notation with optional chaining
const firstName = dynamicProperties.user?.[propertyName];
console.log(firstName); // Output: Jane
Explanation
Optional Chaining works seamlessly with bracket notation, which is useful for accessing properties with special characters or dynamic property names. The code safely retrieves the value associated with the propertyName
variable.
Example 7: Short-circuiting Expression
let counter = 0;
const obj = null;
// The increment expression is never executed
const result = obj?.[counter++];
console.log(counter); // Output: 0
console.log(result); // Output: undefined
Explanation
This demonstrates the short-circuiting behavior of Optional Chaining. Because obj
is null
, the rest of the expression, including the counter++
increment, is never evaluated, which can prevent unintended side effects.