An optional chain is a chain of one or more property accesses and function calls, the first of which begins with the token ?.
.
Long chains of property accesses in JavaScript can be error-prone, as any of them might evaluate to null
or undefined
(also known as “nullish” values).
Checking for property existence on each step easily turns into a deeply-nested structure of if-statements.
// Error prone-version, could throw.
const nameLength = db.user.name.length;
// Less error-prone, but harder to read.
let nameLength;
if (db && db.user && db.user.name) {
nameLength = db.user.name.length;
}
Using the new optional chaining operator, we can rewrite the above example as follows:
// Still checks for errors and is much more readable.
const nameLength = db?.user?.name?.length;
The ?.
operator functions similarly to the .
chaining operator, except that instead of causing an error if a reference is nullish (null
or undefined
), the expression short-circuits with a return value of undefined
.
When used with function calls, it returns undefined
if the given function does not exist.
let result = someInterface.customMethod?.();
Note: If there is a property with such a name and which is not a function, using
?.
will still raise aTypeError
exception (x.y
is not a function).
Optional callbacks or event handlers
// Written as of ES2019
function doSomething(onContent, onError) {
try {
// ... do something with the data
} catch (err) {
if (onError) {
// Testing if onError really exists
onError(err.message);
}
}
}
// Using optional chaining with function calls
function doSomething(onContent, onError) {
try {
// ... do something with the data
} catch (err) {
// no exception if onError is undefined
onError?.(err.message);
}
}
Optional chaining with expressions
let nestedProp = obj?.['prop' + 'Name'];
Optional chaining with an array
let arrayItem = arr?.[42];
Optional chaining is forbidden in write contexts such as
a?.b = c
. Optional deletion as in:delete a ?.b
is supported.
Let's see what babel transpiler does with this Optional chaining syntax
const nameLength = db?.user;
It transpile into
var _db;
var nameLength = (_db = db) === null || _db === void 0 ? void 0 : _db.user;
If you don't know what void 0
does, it evaluates the given expression and then returns undefined
.
Syntax
obj?.prop; // Object
obj?.[expr]; // Expressions
arr?.[index]; // Array
func?.(args); // Function calls
Resources
Thanks for reading!