5 new JavaScript features to improve your code

5 cutting edge JavaScript features to improve your code

JavaScript features are always growing and receiving new ones like operators, syntax constructions, expressions. Many that have been introduced in the recent years and some of them are already second nature, like the fat arrow => expression or the object spread ... operator.

JavaScript features start as proposals

All these JavaScript features start as proposals submitted to the TC 39. The Technical Committe 39 is in charge of standardize:

the general purpose, cross platform, vendor-neutral programming language ECMAScript (JavaScript). This includes the language syntax, semantics, and libraries and complementary technologies that support the language.

There are many JavaScript proposals that we can start adding to our flow today, thanks to Babel, the JavaScript compiler. Some of them offer more clarity, like the numerical separator. Others, like the do expressions, introduce the ability to have complex conditionals mixed with React JSX tags.

Let’s look in this article at 5 JavaScript features that are still in the proposal stages but that we can use with Babel, and will significantly improve your coding experience.

  1. Nullish coalescing operator
  2. Optional chaining operator
  3. Pipeline operator
  4. Numerical separator
  5. Do expressions

Each one has a link to its Babel page where you can see how to configure Babel to use it, although the proposed JavaScript features described here are already included with Babel 7. Each section also has a link to its proposal in the Ecma TC39 organization on GitHub.

Nullish coalescing operator

New JavaScript features: nullish coalescing operator

Proposal: https://github.com/tc39/proposal-nullish-coalescing

Babel: https://babeljs.io/docs/en/next/babel-plugin-proposal-nullish-coalescing-operator.html

This JavaScript proposal describes an operator that allows to provide a fallback value on the right side of the operator when a variable or an object property is undefined. If it’s not undefined, it will use the left side of the operator:

const maybeUndef = undefined;
const val = maybeUndef ?? 2021; // val will be 2021

This is similar to writing it as a ternary operator:

const maybeUndef = undefined;
const val = maybeUndef ? maybeUndef : 2021; // val will be 2021

Note that this operator doesn’t check that the var doesn’t exist. This will throw an error:

const val = maybeUndef ?? 2021;  // throws Error: maybeUndef is not defined

But careful, this operator is not 100% like a ternary operator that returns the first side if the condition evaluated is true. It won’t evaluate values that are usually falsy in JavaScript to false. For example, an empty string won’t be considered false:

const someEmptyString = '';
const val = someEmptyString ?? 'fallback'; // val will be ''

Unlike this nullish coalescing operator, a ternary operator would’ve thrown fallback as the result of this evaluation.

Optional chaining operator

New JavaScript features: optional chaining operator

Proposal: https://github.com/tc39/proposal-optional-chaining

Babel: https://babeljs.io/docs/en/next/babel-plugin-proposal-optional-chaining.html

This operator also works on variables and object properties: it checks whether the nested properties that we’re traversing exist or not. Without this operator, we’ve to check each nested property:

const val = anObj && anObj.aProp && anObj.aProp.aNestedProp

With the new optional chaining operator, we can do something like:

const val = anObj.aProp?.aNestedProp

This looks much more clear and it’s shorter to write. This operator also works with numerical arrays, so it’s good to work with collections:

const val = anObj.anArray[0]?.someProp

And we can stack multiple operators:

const val = anObj.anArray[0]?.someProp?.aNestedProp

And what if we combine this with the previous one, nullish coalescing? We get a syntax that checks that each traversed property exists, and if it doesn’t , provides a fallback value:

const val = anObj.anArray[0]?.someProp ?? 'someDefaultValue'

If any of the values doesn’t exist, it will return someDefaultValue. Combining these two operators is a great way to replace lodash’s get function.

Pipeline operator

New JavaScript features: pipeline operator

Proposal: https://github.com/tc39/proposal-pipeline-operator

Babel: https://babeljs.io/docs/en/babel-plugin-proposal-pipeline-operator

This operator is part of several experimental JavaScript features, and this one provides more readability when chaining several functions together. Consider the following function:

const reverseWords = 
      str => str
		.split( ' ' )
		.reduce( (revStr, word) => [ word, ...revStr ], [] )
		.join( ' ' );

console.log( reverseWords( 'this is fun' ) ); // Output: fun is this

If we need to reuse these partial transformations that are chained together, we can break them into different functions, and then compose the result using them:

const splitBySpace = str => str.split( ' ' );
const reverseArray = arr => arr.reduce( ( acc, cur ) => [ cur, ...acc ], [] );
const joinWithSpace = arr => arr.join( ' ' );

const reverseWords =
    str => joinWithSpace(
        reverseArray(
            splitBySpace(
                str
            )
        )
    );

console.log( reverseWords( 'this is fun' ) ); // Output: fun is this

What is odd about this is that we have to start reading this from the bottom, the splitBySpace line, to the top, in order to understand the transformations applied to string. This goes against our natural reading flow, from top to bottom. We also end up with all those ugly dangling parentheses. This could be written in one line and it’s not much prettier:

const reverseWords = str => joinWithSpace( reverseArray( splitBySpace( str ) ) );

Here, we have to start reading from the center function towards the outer functions, or from right to left, which is counterintuitive for western left-to-right reading.

The pipeline operator can make these constructions much more readable and similar to the chaining we originally had before moving the transformations to separate functions:

const reverseWords =
    str => str
        |> splitBySpace
        |> reverseArray
        |> joinWithSpace;

Now the transformations applied are written similarly to our way of writing, from top to bottom, they’re more clear to read, and we don’t have any parentheses dangling around. Success!

Numerical separator

New JavaScript features: numerical separator

Proposal: https://github.com/tc39/proposal-numeric-separator

Babel: https://babeljs.io/docs/en/next/babel-plugin-proposal-numeric-separator.html

This numerical separator is different to the other JavaScript features since it’s not an operator. It’s a syntax construction that makes numeric literals more readable by creating a visual separation between groups of digits. Large numeric literals are difficult to parse and understand quickly, particularly when a digit is repeated multiple times. For example:

const longNum = 1000000000000;

It’s hard to understand with a quick glance. This separator makes it more readable:

const longNum = 1_000_000_000_000;

Now we can quickly understand that this is a trillion.

Do expressions

New JavaScript features: do expressions

Proposal: https://github.com/tc39/proposal-do-expressions

Babel: https://babeljs.io/docs/en/babel-plugin-proposal-do-expressions

The last one of the new JavaScript features that we’ll go through is an expression that can be evaluated. The result of this expression comes after executing a block that can have multiple statements inside. We can easily understand do expressions if we translate a ternary operator expression like this one:

const res = isCold( color ) ? 'light-blue' : 'orange';

We would write the equivalent do{} expression like this:

const res = do {
    if ( isCold( color ) ) {
        'light-blue';
    } else {
        'orange';
    }
};

Note that we don’t have to return the value since this is not a function. While in this particular case, this can be written more succinctly as a ternary, the do expressions are much more powerful, allowing for multiple statements, for example:

const res = do {
    if ( isCold( color ) ) {
        'light-blue';
    } else if ( isHot( color ) ) {
        'orange';
    } else if ( isRain( color ) ) {
        'purple';
    } else {
        'green';
    }
};

Where this is really powerful is in JSX, where we can mix it with its tags without having to compute the result externally first. For example, we could do the following if we were using React to render these components:

const MyComp = ( { color } ) => (
    <div>
        {
            do {
                if ( isCold( color ) ) {
                    <LightBlue />;
                } else if ( isHot( color ) ) {
                    <Orange />;
                } else if ( isRain( color ) ) {
                    <Purple />;
                } else {
                    <Green/>;
                }
            }
        }
    </div>
);

More JavaScript proposals

There are more proposals being discussed every day to add more interesting features to the JavaScript language. An ever growing list of these proposed JavaScript features can be read at https://github.com/tc39/proposals#ecmascript-proposals. The proposals here are close to completion and thus close to being added to the ECMAScript standard as explained in this table that describes the acceptance process.

Some of the new JavaScript features that we explored in this article, like the do expressions or the pipeline operator are stage 1 proposals, which mean they still have a way to go before becoming part of the ECMAScript standard.

Advertisements

Leave a Reply