[ES11(2020)] optional chain operator and null value merging operator

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"

Keywords: Javascript ECMAScript html5

Added by blakogre on Sat, 12 Feb 2022 01:03:44 +0200