Optional Chaining in JavaScript: Methods & Indexing
Optional chaining (?.) in JavaScript provides a safe way
to access object properties, execute methods, and look up dynamic keys
or array elements without having to manually verify that each reference
in the chain is valid. When an evaluation encounters a null
or undefined value, the expression short-circuits and
evaluates to undefined instead of throwing a
TypeError. This article explains how the optional chaining
operator functions when applied specifically to method invocations and
dynamic property indexing.
Optional Method Invocations
Optional chaining can be used to call a method that may or may not
exist on an object using the ?.() syntax.
Syntax and Basic Usage
When calling a method that might not be defined, place
?. before the parentheses:
const user = {
name: "Alex",
getRole: () => "Admin"
};
// Calling an existing method
console.log(user.getRole?.()); // Output: "Admin"
// Calling a non-existent method
console.log(user.getPermissions?.()); // Output: undefinedIf the object itself might be null or
undefined, chain the operator before the method name as
well:
const guest = null;
// Safe call on a potentially nullish object
console.log(guest?.getRole?.()); // Output: undefinedImportant Caveat: Non-Function Types
Optional chaining only checks if the value before ?.()
is null or undefined. If the property exists
but contains a value that is not a callable function (such as a string,
number, or object), JavaScript will still throw a
TypeError.
const config = {
customAction: "not a function"
};
// Throws TypeError: config.customAction is not a function
config.customAction?.();Optional Property Indexing (Bracket Notation)
Optional property indexing allows safe access to dynamic object
properties and array elements using the ?.[] syntax.
Dynamic Object Keys
When looking up object properties using variables or computed keys,
place ?. before the opening bracket:
const themeSettings = {
dark: { background: "#000" }
};
const userPreference = "light";
// Accessing a key that does not exist
console.log(themeSettings?.[userPreference]?.background); // Output: undefinedArray Element Access
The ?.[] notation works the same way for arrays,
guarding against indexing into null or
undefined collections:
function getFirstItem(list) {
return list?.[0];
}
console.log(getFirstItem(["apple", "banana"])); // Output: "apple"
console.log(getFirstItem(null)); // Output: undefined
console.log(getFirstItem(undefined)); // Output: undefinedShort-Circuit Evaluation
Optional chaining relies on short-circuiting. If the target on the
left-hand side of ?. evaluates to null or
undefined, any subsequent expressions, method arguments, or
nested property lookups on that chain are not executed.
let counter = 0;
const increment = () => ++counter;
const handler = null;
// increment() is never called because handler is null
handler?.[increment()]();
console.log(counter); // Output: 0Combining Indexing and Method Invocations
You can combine both techniques to safely retrieve a function by dynamic key and execute it in a single statement:
const actions = {
save: () => "Saved successfully!"
};
const actionName = "delete";
// Safely attempts to find and invoke the dynamic method
const result = actions?.[actionName]?.();
console.log(result); // Output: undefinedBy using ?.() for method calls and ?.[] for
computed lookups, you can write concise, defensive JavaScript code that
avoids runtime
TypeError: Cannot read properties of undefined
exceptions.