Optional chain operator
Optional chain operator (?.) It is not necessary to verify whether the value of each link in the chain is explicitly valid, but whether it is allowed to read the value of each link in the chain The function of the operator is similar to The difference of chain operator is that it will not cause an error when the reference is null (null or undefined). The short circuit return value of this expression is undefined. When used with a function call, undefined is returned if the given function does not exist.
When trying to access an object property that may not exist, the optional chain operator will make the expression shorter and more concise. It is necessary to determine which attributes of the object chain exist, and if they do not exist, they are also optional.
const adventurer = { name: 'Alice', cat: { name: 'Dinah' } }; // Direct operation of unknown variables and methods may report errors console.log(adventurer.aa.bb) // Uncaught TypeError: Cannot read property 'bb' of undefined console.log(adventurer.aa()) // Uncaught TypeError: adventurer.aa is not a function // Using the optional chain operator can avoid error reporting const dogName = adventurer.dog?.name; console.log(dogName); // undefined console.log(adventurer.someNonExistentMethod?.()); // undefined
Syntax:
obj?.prop // object obj?.[expr] // object arr?.[index] // array func?.(args) // function
When the reference or function of the connected object may be undefined or null, the optional chain operator provides a way to simplify the value access of the connected object.
For example, consider an object obj that has a nested structure. If the optional chain is not used, when finding a deeply nested sub attribute, the reference between them needs to be verified, for example:
// Previous writing let nestedProp = obj.first && obj.first.second; // Optional chain operator let nestedProp = obj.first?.second;
By using Operator substitution Operator, JavaScript will try to access obj first. Before second, implicitly check and determine obj First is neither null nor undefined. If obj If first is null or undefined, the expression will be short circuited and returned undefined directly.
Equivalent to the following expression, but no temporary variable is actually created:
let temp = obj.first; let nestedProp = ((temp === null || temp === undefined) ? undefined : temp.second);
Optional chain and function use
let result = someInterface.customMethod?.();
Function uses optional chain operator scenarios:
function doSomething(onContent, onError) { try { // ... do something with the data } catch (err) { onError?.(err.message); // If onError is undefined, there will be no exception } }
Optional chains and expressions
When using square brackets and attribute names to access attributes, you can also use the optional chain operator:
let nestedProp = obj?.['prop' + 'Name'];
Optional chains can be used for assignment:
let object = {}; object?.property = 1; // Uncaught SyntaxError: Invalid left-hand side in assignment
Optional chain access array
let arrayItem = arr?.[42];
Null coalescing operator
Null merge operator (?) Is a logical operator. When the operand on the left is null or undefined, it returns the operand on the right. Otherwise, it returns the operand on the left.
Unlike the logical or operator (|), the logical or operator returns the right operand when the left operand is false. That is, if you use 𞓜 to set default values for some variables, you may encounter unexpected behavior. For example, when it is a false value (for example, '' or 0). See the example below.
const foo = null ?? 'default string'; console.log(foo); // "default string" const baz = 0 ?? 42; console.log(baz); // 0
Use null merge operator
console.log(null ?? "defaultValue1") // "defaultValue1" console.log(undefined ?? "defaultValue2") // "defaultValue2" console.log("" ?? "defaultValue3") // "" console.log(0 ?? "defaultValue4") // 0 console.log(40 ?? "defaultValue5") // 40
Assign default values to variables
In the past, if you wanted to assign a default value to a variable, you usually used the logic or operator (|):
let foo; // foo is never assigned any value so it is still undefined let someDummyText = foo || 'Hello!';
However, since 𞓜 is a Boolean logical operator, the operand on the left is cast to a Boolean value for evaluation. Any false values (0, '', NaN, null, undefined) will not be returned. This leads to unpredictable consequences if you use 0, '' or NaN as valid values.
let count = 0; let text = ""; let qty = count || 42; let message = text || "hi!"; console.log(qty); // 42 instead of 0 console.log(message); // "hi!", Not ''
The null merge operator avoids this trap by returning the second operand only when the first operand is null or undefined (not other false values):
let myText = ''; let notFalsyText = myText || 'Hello world'; console.log(notFalsyText); // Hello world let preservingFalsy = myText ?? 'Hi neighborhood'; console.log(preservingFalsy); // ''
short circuit
Similar to the OR AND logical operators, the right expression is not evaluated when the left expression is not null OR undefined.
function A() { console.log('function A Called'); return undefined; } function B() { console.log('function B Called'); return false; } function C() { console.log('function C Called'); return "foo"; } console.log( A() ?? C() ); // Print "function A called", "function C called" and "foo" successively // A() returns undefined, so the expressions on both sides of the operator are executed console.log( B() ?? C() ); // Print "function B called" and "false" successively // B() returned false (neither null nor undefined) // So the right expression is not executed
Cannot be used directly with AND OR operators
null || undefined ?? "foo"; // Throw syntax error true || undefined ?? "foo"; // Throw syntax error
However, parentheses are added to indicate the operation priority. There is no problem:
(null || undefined ) ?? "foo"; // Return to "foo"
And optional chain operator (?.) Relationship between
let customer = { name: "Carl", details: { age: 82 } }; let customerCity = customer?.city ?? "Dark City"; console.log(customerCity); // "Dark city"