Recently, I found that some students in my team did not know the two new operators Optional chaining and Nullish coalescing, which happened to be promoted.

background

Optional chaining and Nullish coalescing are now included in the ECMA-262 standard, but the compatibility is far from satisfactory, as follows:

babel

Optional chainingintroduce

The Optional chaining is to solve the problem of inanimate Cannot read property ‘foo’ of undefined errors or a && A.B&& A.B.C&& A.B.C.D. Logical and operators or ternary operators. With Optional chaining, we can elegantly retrieve data that might not exist.

The Optional chaining operator is defined to interrupt the value operation when the left-hand operand is null and return undefined. Method call interrupts when method is null and returns undefined.

constfoo = a? .b? .c? .d;Copy the code

Compared to a long string of logic and operators, not only elegant and beautiful, but also convenient, more readable, logic and sometimes lazy do not write, but since the use of Optional chaining, no longer need to be lazy, attribute value is so simple and stable, no longer afraid of missing the attribute.

Optional chaining has three standard syntax:

// Static attributesa? .b? .c.d// Dynamic attributesa? .[b]? .c.d// method calla? .b? . ()Copy the code

Note that Optional chaining cannot be used with digits because it is syntaxically coeval.

a?3.:0; a? .3]
Copy the code

So remember to use [] for numbers.

Optional chaining also supports delete:

deletea? .b? .c;Copy the code

Note that the above operation will only delete A.B.C but not a.b regardless of the value of A.b.

Nullish coalescingintroduce

Coalescing Nullish coalescing and Optional chaining are a couple of good gay friends, used to make some default Settings.

The definition of the Nullish coalescing operator is as follows: If the left operand is null or undefined, the right operand is returned. Otherwise, the left operand is returned.

constfoo = a? .b? .c? .d ??'bar';
Copy the code

Some of you might wonder, isn’t this the same thing as logic?

constfoo = a? .b? .c? .d ||'bar';
Copy the code

Coalescing is not the same as the name suggests: Nullish coalescing is more reasonable in some boundary cases, such as when the left operand is 0 and “” is an empty string, so that the judgment of some boundary values can be reduced.

null ?? 'foo'; // 'foo'
undefined ?? 'foo'; // 'foo'
0 ?? 'foo'; / / 0
' ' ?? 'foo'; / /"

null || 'foo'; // 'foo'
undefined || 'foo'; // 'foo'
0 || 'foo'; // 'foo'
' ' || 'foo'; // 'foo'
Copy the code

How to use

These two new operators are actually included in the new version of preset-env, and if your project is preset-env is new, congratulations 🎉, you don’t need to do anything extra to preset.

However, if this is an older version of preset-env, a plugin needs to be installed to enable it:

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

After installation, don’t forget to enable Babel configuration:

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

Babel escape

Take a look at how Babel escapes Optional chaining and Nullish coalescing.

Escape of Optional chaining

a? .b? .[c]? . ()deletea? .b? .c// Babel escape =====>
"use strict";
var _a, _a$b, _a$b$c, _a2, _a2$b;
(_a = a) === null || _a === void 0 ? void 0 : (_a$b = _a.b) === null || _a$b === void 0 ? void 0 : (_a$b$c = _a$b[c]) === null || _a$b$c === void 0 ? void 0 : _a$b$c.call(_a$b);
(_a2 = a) === null || _a2 === void 0 ? true : (_a2$b = _a2.b) === null || _a2$b === void 0 ? true : delete _a2$b.c;
Copy the code

Careful students can find a few more noteworthy points.

Pay attention to the point

  1. babelCaches the value of an attribute every time it is evaluated instead of writing it directly in normal codea && a.b && a.b.cTo ensure consistency with the native implementation, ensure that the value of each attribute is fetched only once, avoiding inconsistent value counts when getter attributes are obtained.
  2. babelIt is not used directly to determine whether a value is null== nullI’m using something a little bit more cumbersome=== null || === void 0This is mainly for compatibilitydocument.allAbout thedocument.allI’ll write it in the back.

Description Nullish coalescing is escaped

a ?? b
// Babel escape =====>
"use strict";
var_a; (_a = a) ! = =null&& _a ! = =void 0 ? _a : b;
Copy the code

Can notice is compatible to the document. The same all, Nullish coalescing also USES the = = = null | | = = = void 0 for judgment.

document.all

Document. all is a strange value. It is a collection of all elements in document, but it is a false value and is a special null value.

document.all || 1 / / 1
document.all == null // true
document.all === null // false
document.all === undefined // false
Copy the code

Document. all is a residual property, and these features are also for some previous compatibility purposes. It’s already deprecated in HTML5, so you don’t need to know too much about it. If you are interested, take a look at the documentation for MDN document. all.

loose

Since document.all is a deprecated property, there is no need for Babel to escape a lot of meaningless code because of a deprecated property. We can do this by enabling the loose property of the plug-in:

{
  "plugins": [["@babel/plugin-proposal-optional-chaining", {"loose": false}], ["@babel/plugin-proposal-nullish-coalescing-operator", {"loose": false}}]]Copy the code

If preset-env is easier to integrate, just set loose in preset-env to true.

Take a look at the compiled code:

a? .b? .[c]? . ()// Babel escape =====>
"use strict";
var _a, _a$b, _a$b$c;
(_a = a) == null ? void 0 : (_a$b = _a.b) == null ? void 0 : (_a$b$c = _a$b[c]) == null ? void 0 : _a$b$c.call(_a$b);
Copy the code
a ?? b
// Babel escape =====>
"use strict";
var_a; (_a = a) ! =null ? _a : b;
Copy the code

The code is suddenly much simpler. You can also add an alarm to ESLint if you are concerned about a team member misusing document.all.

conclusion

Optional chaining and Nullish coalescing have been included in the standard for some time, and can greatly increase the elegance and readability of code such as attribute fetching and default setting. Reduce various Cannot read property ‘foo’ of undefined error cases. Wait for what? Let’s just use it.

If you find this article useful, please feel free to like 👍