The chain judgment operator (? .).

Very easy to use, commonly used, with Null judgment operator use, better effect, perfect!

Here, the code:

We usually need to make multiple judgments when obtaining the attribute values of multiple layers of an object. If you do not judge, an error is reported if one is empty, leading to the failure to continue.

// error

const  firstName = message.body.user.firstName;



// ok

const firstName = (message

  && message.body

  && message.body.user

  && message.body.user.firstName) || 'default';

Copy the code

You can also use the ternary operator, right? In the following example, we must check whether fooInput exists before reading fooinput. value.

const fooInput = myForm.querySelector('input[name=foo]')

const fooValue = fooInput ? fooInput.value : undefined

Copy the code

And then, what do we use? The. Operator looks amazing:

constfirstName = message? .body? .user? .firstName ||'default';

const fooValue = myForm.querySelector('input[name=foo]')? .value

Copy the code

In one go, check whether the object on the left is null or undefined during the chain call. If so, it does not proceed further and returns undefined

The chain judgment operator has three uses.

  • obj? .prop // Object properties
  • obj? [expr] / / same as above
  • func? . (… Args) // Call a function or object method
"#C0FFEE".match(/#([A-Z]+)/i)? .1]  // Returns null if there is no match, returns an array if there is a match



a? .b

/ / is equivalent to

a == null ? undefined : a.b



a? .[x]

/ / is equivalent to

a == null ? undefined : a[x]



a? .b()

/ / is equivalent to

a == null ? undefined : a.b()



a? . ()

/ / is equivalent to

a == null ? undefined : a()

Copy the code

In the code above, pay particular attention to the last two forms, if a? A.b in.b() is not a function, then a? .b() is an error. a? If a is not null or undefined, but is not a function, then a? .() will report an error.

There are several caveats to using this operator.

(1) Short circuit mechanism

? The. Operator acts as a short-circuit mechanism that stops executing if the condition is not met.

a? .[++x]

/ / is equivalent to

a == null ? undefined : a[++x]

Copy the code

In the above code, if a is undefined or null, x is not incremented. That is, once the chain judgment operator is true, the expression on the right is no longer evaluated.

(2) Delete operator

deletea? .b

/ / is equivalent to

a == null ? undefined : delete a.b

Copy the code

In the above code, if a is undefined or null, undefined is returned instead of delete.

(3) The influence of parentheses

If the attribute chain has parentheses, the chain judgment operator has no effect outside the parentheses, only inside the parentheses.

(a? .b).c

/ / equivalent to the

(a == null ? undefined : a.b).c

Copy the code

In the code above,? .c after the parentheses is always executed, regardless of whether the a object exists.

In general, use? The. Operator should not use parentheses.

(4) Error reporting occasions

The following syntax is forbidden and an error may be reported.

// constructor

newa? . ()

newa? .b()



// There is a template string to the right of the chain judgment operator

a? .`{b}`

a? .b`{c}`



// To the left of the chain judgment operator is super

super? . ()

super? .foo



// The chain operator is used to the left of the assignment operator

a? .b = c

Copy the code

(5) The right side shall not be a decimal value

To ensure compatibility with previous code, allow foo? .3:0 is resolved to foo? .3:0, so if? .followed by a decimal number, then? Instead of being treated as a complete operator, it is treated as a ternary operator, that is, the decimal point is assigned to the following decimal number, forming a decimal number.

Null judgment operator (??)

When reading object properties, you sometimes need to specify a default value for an attribute if its value is null or undefined. Common practice is to pass | | operators specify a default value.

const headerText = response.settings.headerText || 'Hello, world! ';

const animationDuration = response.settings.animationDuration || 300;

const showSplashScreen = response.settings.showSplashScreen || true;

Copy the code

The three lines of code above all through the | | operator to specify a default value, if the value of the attribute to “false or 0, the default value will take effect.

To avoid this, ES2020 introduces a new Null judgment operator?? . Its behavior similar | |, but only the operator to the left of the value is null or undefined, will return to the right of the value.

const headerText = response.settings.headerText ?? 'Hello, world! ';

const animationDuration = response.settings.animationDuration ?? 300;

const showSplashScreen = response.settings.showSplashScreen ?? true;

Copy the code

In the above code, the default value is valid only if the left attribute value is null or undefined.

One of the purposes of this operator is to check the chain operator, okay? . Set the default value for null or undefined.

constanimationDuration = response.settings? .animationDuration ??300;

Copy the code

The above code, if the response Settings is null or undefined, or response. Settings. AnimationDuration is null or undefined, will return to the default value of 300. In other words, this line of code contains two levels of attribute judgment.

This operator is good for determining whether a function argument is assigned:

function Component(props{

  constenable = props? .enable ??true;

  / /...

}



// The above code is equivalent to

function Component(props{

  const {

    enable: enable = true.

  } = props;

  / /...

}

Copy the code

?? Have an operation priority issues, it with && and | | priority is tall what is low. The rule now is that if multiple logical operators are used together, parentheses must indicate precedence or an error will be reported.

/ / an error

lhs && middle ?? rhs

lhs ?? middle && rhs

lhs || middle ?? rhs

lhs ?? middle || rhs

Copy the code

All four expressions above report errors and must be parentheses indicating precedence.

(lhs && middle) ?? rhs;

lhs && (middle ?? rhs);



(lhs ?? middle) && rhs;

lhs ?? (middle && rhs);



(lhs || middle) ?? rhs;

lhs || (middle ?? rhs);



(lhs ?? middle) || rhs;

lhs ?? (middle || rhs);

Copy the code

ES version update benefits

In the Tencent developer conference a few months ago, a warm-hearted citizen asked the ES developer this question, just borrow the topic of this article, here to share with you!

As for the ES release update, why is it that ES5 to ES6 is a huge book-style update, with only a few new technologies added in subsequent releases?

Reason: “afraid you learn not to move!”

In fact, the former update way, to learn so many things, so thick a book, will give a person a kind of daunting feeling, did not enter the door on the first kneel.

For the latter, just a few new technologies, maybe half a day, can be fully mastered and the final result, the harvest of the sense of achievement will be more and faster!

So, learning is a lifetime thing, either accept or change, good luck!!