optional chaining
operator (
?.
) permits reading the value of a property located deep within a chain of connected objects without having to expressly validate that each reference in the chain is valid.
?.
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.
This results in shorter and simpler expressions when accessing chained properties when the possibility exists that a reference may be missing. It can also be helpful while exploring the content of an object when there's no known guarantee as to which properties are required.
The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone https://github.com/mdn/interactive-examples and send us a pull request.obj?.prop obj?.[expr] arr?.[index] func?.(args)
The optional chaining operator provides a way to simplify accessing values through connected objects when it's possible that a reference or function may be
undefined
or
null
.
For example, consider an object
obj
which has a nested structure. Without optional chaining, looking up a deeply-nested subproperty requires validating the references in between, such as:
let nestedProp = obj.first && obj.first.second;
值
obj.first
is confirmed to be non-
null
(and non-
undefined
) before then accessing the value of
obj.first.second
. This prevents the error that would occur if you simply accessed
obj.first.second
directly without testing
obj.first
.
With the optional chaining operator (
?.
), however, you don't have to explicitly test and short-circuit based on the state of
obj.first
before trying to access
obj.first.second
:
let nestedProp = obj.first?.second;
By using the
?.
operator instead of just
.
, JavaScript knows to implicitly check to be sure
obj.first
不是
null
or
undefined
before attempting to access
obj.first.second
。若
obj.first
is
null
or
undefined
, the expression automatically short-circuits, returning
undefined
.
This is equivalent to the following, except that the temporary variable is in fact not created:
let temp = obj.first; let nestedProp = ((temp === null || temp === undefined) ? undefined : temp.second);
You can use optional chaining when attempting to call a method which may not exist. This can be helpful, for example, when using an API in which a method might be unavailable, either due to the age of the implementation or because of a feature which isn't available on the user's device.
Using optional chaining with function calls causes the expression to automatically return
undefined
instead of throwing an exception if the method isn't found:
let result = someInterface.customMethod?.();
注意:
If there is a property with such a name and which is not a function, using
?.
will still raise a
TypeError
exception (
someInterface.customMethod is not a function
).
注意:
若
someInterface
itself is
null
or
undefined
,
TypeError
exception will still be raised (
someInterface is null
). If you expect that
someInterface
itself may be
null
or
undefined
, you have to use
?.
at this position as well:
someInterface?.customMethod?.()
If you use callbacks or fetch methods from an object with
a destructuring assignment
, you may have non-existent values that you cannot call as functions unless you have tested their existence. Using
?.
, you can avoid this extra test:
// 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) {
onError?.(err.message); // no exception if onError is undefined
}
}
You can also use the optional chaining operator when accessing properties with an expression using the bracket notation of the property accessor :
let nestedProp = obj?.['prop' + 'Name'];
let object = {};
object?.property = 1; // Uncaught SyntaxError: Invalid left-hand side in assignment
let arrayItem = arr?.[42];
This example looks for the value of the
name
property for the member
bar
in a map when there is no such member. The result is therefore
undefined
.
let myMap = new Map();
myMap.set("foo", {name: "baz", desc: "inga"});
let nameBar = myMap.get("bar")?.name;
When using optional chaining with expressions, if the left operand is
null
or
undefined
, the expression will not be evaluated. For instance:
let potentiallyNullObj = null; let x = 0; let prop = potentiallyNullObj?.[x++]; console.log(x); // 0 as x was not incremented
With nested structures, it is possible to use optional chaining multiple times:
let customer = {
name: "Carl",
details: {
age: 82,
location: "Paradise Falls" // detailed address is unknown
}
};
let customerCity = customer.details?.address?.city;
// … this also works with optional chaining function call
let duration = vacations.trip?.getTime?.();
nullish coalescing operator may be used after optional chaining in order to build a default value when none was found:
let customer = {
name: "Carl",
details: { age: 82 }
};
const customerCity = customer?.city ?? "Unknown city";
console.log(customerCity); // Unknown city
| 规范 |
|---|
|
ECMAScript (ECMA-262)
The definition of 'optional expression' in that specification. |
| Desktop | Mobile | Server | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Optional chaining operator (
?.
)
|
Chrome
80
|
Edge
80
|
Firefox 74 | IE No |
Opera
67
|
Safari 13.1 | WebView Android 80 |
Chrome Android
80
|
Firefox Android No | Opera Android No | Safari iOS 13.4 | Samsung Internet Android No | nodejs 14.0.0 |
完整支持
不支持
用户必须明确启用此特征。
The following table provides a daily implementation status for this feature because this feature has not yet reached cross-browser stability. The data is generated by running the relevant feature tests in Test262 , the standard test suite of JavaScript, in the nightly build, or the latest release of each browser's JavaScript engine.