preface

The optional chaining operators have been added to Babel for a long time, but I have not used them in practice. The first is that I have a partial understanding of this feature, and the second is that I have not formed this habit. So that it can be better used in the next project practice.

Introduction to optional chain operators

Because JavaScript is a dynamic language, we are always careful to do a lot of defensive programming when accessing object properties. If obj is null, you will get an error message from the browser, 😂. If obj is null, you will get an error message from the browser.



obj && obj.name






obj.a.b.c.d.name












  1. lodash.get
  2. Use ES6 deconstruction (also need to peel off layers to write, deep deconstruction is still cumbersome)
  3. Implement safeGet yourself, or learn the get method in you-dont-need-loDash
const get = (obj, path, defaultValue = undefined) = > {
  const travel = regexp= >
    String.prototype.split
      .call(path, regexp)
      .filter(Boolean)
      .reduce((res, key) = >(res ! = =null&& res ! = =undefined ? res[key] : res), obj);
  const result = travel(/ [[\]] +? /) || travel(/ [[\]] +? /);
  return result === undefined || result === obj ? defaultValue : result;
};
Copy the code

What happens when you have optional chains? Let’s start with a chestnut 🌰.

const obj = { a: { b: [{ name: 'obj'}}}]// The original way
console.log(obj && obj.a && obj.a.b.length && obj.a.b[0].name)

// Optional chain writing
console.log(obj? .a? .b? .0]? .name);// obj
console.log(obj? .b? .c? .d)// undefined
Copy the code

It’s a huge simplification of judgment, but









nullish
undefined
null
undefined






Null value merge operation


const obj = { a : { name: 'obj'} } obj? .a? .b ??'hello world' // hello world
Copy the code

It is also important to note that the nullish operator will only return the right-hand expression if the left-hand side is nullish. And we used to have logic or | | operation, is if the left false value, it returns to the right of the expression.

How is it used in a project

Node

Node.js is available with native support in v14.0.0 and above.

The front-end project

You can experience it with the help of the Babel plugin. The installation

yarn add @babel/plugin-proposal-optional-chaining --dev
Copy the code

use

{
  "plugins": ["@babel/plugin-proposal-optional-chaining"]
}
Copy the code

Babel is available at www.babel

Vue template

Unfortunately, not support ~ see especially big.

The basic use

Read object properties

const obj = { a: { name: 'obj'} } obj? .a? .name// obj
Copy the code

Read object properties, dynamic keys

const obj = { a: { name: 'obj'} } obj? .a? .'name'] // obj
Copy the code

Array subscript access

const skills = ['CSS'.'HTML'.'JavaScript'.'Vue'] skills? .3] // Vue
Copy the code

A function call

const obj = {
 fun() {
   console.log('hello world') } } obj? .fun? . ()// hello world
Copy the code

Use the advanced

Replace the ternary operator

foo ? foo.bar : defaultValue // beforefoo? .bar ?? defaultValue// after
Copy the code

Simplified regular expression values

// before
let match = "#C0FFEE".match(/#([A-Z0-9]+)/i)? .1]
let hex = match && match[1]

// after
let hex = "#C0FFEE".match(/#([A-Z0-9]+)/i)? .1]
Copy the code


Property to check

// before 
if (element.prepend) element.prepend(otherElement);

// afterelement? .prepend(otherElement)Copy the code


Avoid overuse

Although we have a hammer 🔨, we cannot see everything as a nail.

Multiple actions need to be performed after the if judgment is made

// before
if (foo) {
  something(foo.bar); 
  somethingElse(foo.baz);
  andOneLastThing(foo.yolo);
}


// aftersomething(foo? .bar); somethingElse(foo? .baz); andOneLastThing(foo? .yolo);Copy the code

In this case, we’ll go from checking once to checking three times… And without adding an attribute, a method has to be judged again.








Omit the assignment judgment

// before
if (foo && foo.bar) {
 foo.bar.baz = someValue; 
}

// afterfoo? .bar? .baz = someValueCopy the code

Look at this code, do you think it’s a normal operation?









Obviously, a running error hit us in the face

So optional chain is good, but also can’t mess with it!

Use a trap

Judgment of strict equality

Let’s start with a piece of code

if(foo? .bar === baz) {// todo
}
Copy the code

I looked at it. There seems to be no problem, huh?



Bug
Bug


  1. whenfooThe optional chain expression returns when it does not existundefined
  2. whenbazThe value of the variable isundefinedwhen

Congratulations, logic is working, and the same thing happens when judgments are not equal.

Judge non-strict equality

Look at the code

if(foo? .bar ! == SomeValue) {// TODO    
}
Copy the code

As mentioned above, if the optional chain expression short-circuited returns undefined, then if someValue is any other value, then you might as well bury an Easter egg in your own code… For example, undefined! == ‘string’ …

conclusion

This article introduces optional chains, basic syntax, and some usage scenarios. You must have learned them already. The next time you encounter a deep nested object thrown by the back end, don’t be afraid ~