What’s new in ES2018 (ES9)

Hello JavaScripters! 👋

A new JavaScript version is here packed with a bunch of new features and updates, let’s get down to it, shall we!

javascript coding
Photo by Irvan Smith on Unsplash

Me personally I am looking forward to one particular udpate, i.e. the Object rest/spread operator that will enable me and certainly you to write way less code (in quantity) and way more code (in readability) as the same time!

We’re get to that, so let’s look at what’s new.

Table of contents:

  1. Template literal revision
  2. Regular expressions
    1. Look behind assertions
    2. Unicode property escapes
    3. Named capturing groups
    4. “Match all” flag, including new lines
  3. Asynchronous iterations
  4. Promise.prototype.finally()
  5. Object rest/spread operator

Pretty interesting, right? 🤔 So let’s dive right in and we’ll start with:

1. Template Literal Revision

The first update, for me personally a bit unimportant. It is a revision of template literals. I have never needed to accomplish nothing even close to this one so I will just provide a bit of description about the matter and also links where you can get detailed information in case you need it:

Tagged templates should allow the embedding of languages (for example DSLs, or LaTeX), where other escapes sequences are common. The ECMAScript proposal Template Literal Revision (Stage 4, to be integrated in the ECMAScript 2018 standard) removes the syntax restriction of ECMAScript escape sequences from tagged templates.

However, illegal escape sequences must still be represented in the “cooked” representation. They will show up as undefined element in the “cooked” array.

Read more on developer.mozilla.org

You can find more information on the links below:

2. Regular expressions

This (sometime called) mysterious part of JavaScript got its update as well. This time it was a bit extensive update and you’d better pay attentions since if you work with RegExp objects often, you’ll find the updates that much more useful.

2.1 Lookbehind assertions

This update brings a “missing brother” into the regex family.

We already know lookahead assertions in RegExp, meaning that whatever text text comes “next” of what you want to match must match the assertion, but nothing else happens – or in other words nothing is captured and the assertion doesn’t contribute to the overall matched string.

Now JavaScript introduces the exact opposite, called lookbehind assertion. That basically means that the text preceding the current location must batch the assertion (but nothing else happens).

Consider the following example:

Example #1: (lookbehind assertion in action)

'€dollars %dollars dollars'.replace(/(?<=\€)dollars/g, 'euros');
// '€euros %dollars dollars'

As you can see, the dollars is only replaced, if it is preceded by a € sign.

Of course, this can be accomplished with capturing and replacing the value, but the lookbehind assertion is that much more readable.

Example #2: (lookbehind assertion alternative)

'€dollars %dollars dollars'.replace(/(\€)dollars/g, '$1euros'); 
// '€bar %dollars dollars'

2.2 Unicode property escapes

If you ever wanted the regular expressions to look more readable, this is the time your dreams come true.

You see, up until now you could have used \d for matching decimals, \w for matching alphanumerical characters, \s whitespaces and so on.

But, let’s be honest here, how likes it? The answer if probably very few people! 😆

Wouldn’t it be great if we could just write “regex, please match emoji” or “hey regex, please match greek letters only” or hear this: “regex, just match currency symbols, would ya“?

Guess what!

That’s possible

Look at the following example:

Example #1:

/^\p{Emoji}+$/u.test('🙃🙃'); // => true
/^\p{Script=Greek}+$/u.test('ηδμ'); // => true
/^\p{Currency_Symbol}+$/u.test('€$'); // => true

So who’s gonna love regular expressions from now on, say ay! 😍

If you want to see the full list of the proposed character classes, have a look at the specification.

2.2.1 Negation of unicode property escape

To match a certain character group you should use \p{...}, but if you want NOT to match a specific character group, use a negation.

It is just an uppercase P, just like so: \P{...}.

Example #2: (negation in action)

/^\P{Emoji}+$/u.test('🙃🙃'); // => false
/^\P{Emoji}+$/u.test('lorem ipsum'); // => true

/^\P{Script=Greek}+$/u.test('ηδμ'); // => false
/^\P{Script=Greek}+$/u.test('lorem ipsum'); // => true

/^\P{Currency_Symbol}+$/u.test('€$'); // => false
/^\P{Currency_Symbol}+$/u.test('lorem ipsum'); // => true

2.3 Named capturing groups

A bit earlier I was talking about readability of regular expressions. Here’s another update in regard with this.

Consider the following example:

Example #1: (matching a date Y-m-d)

const regex = /(\d{4})-(\d{2})-(\d{2})/
const result = regex.exec("2020-02-02");

//["2020-02-02", "2020", "02", "02", index: 0, input: "2020-02-02"]

Well, not that it’s some kind of problem with that, just when working with dates, it would be much more readable, if we could have just marked a capturing group with a name and access it afterwards.

Well.

That’s exactly what this update brings now. A regular expression for a new response key called groups that will contain captured data from groups you put a name on

The named capturing group has the following format: (?<name>...). The question mark, the greater than and the lower than are a part of the syntax.

Look at the following example:

Example #2: (named capturing groups in action)

const re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/; const match = re.exec('2019-01-10');

console.log(match.groups); // => {year: "2019", month: "01", day: "10"}
console.log(match.groups.year); // => 2019
console.log(match.groups.month); // => 01
console.log(match.groups.day); // => 10

2.4 “Match all” flag, including new lines

In JavaScript, there is a . matching character, that matches every single character – excerpt for new lines (\n, \r).

So for example if you wanted to match something spanning across multiple lines, good luck doing that in JavaScript 😀.

Well, there were multiple ways how to accomplish this, for example:

Example #1: (match any digit character and match any non-digit character)

console.log(/one[\d\D]two/.test('one\ntwo')); // => true

If you were to use a “dot” character, it would not work, since it is not matching new line characters.

Example #2:

/one.two/.test('one\ntwo'); // => false

And this is where JavaScript introduces a flag s, that will tell the regular expression that the . dot macthing character should include new lines as well.

You can see it on the example below:

Example #3:

/one.two/s.test('one\ntwo'); // => true

3. Asynchronous iterations

ES2017 or ES8 introduced one of the breakthrough in JavaScript programming in my opinion, i.e. async/await.

The best thing about it was an option to create a single javascript function, that handles upload of a file to a webserver, for example:

Example #1: (chunk file upload with async await)

const uploadChunk = async (chunk) => {
    return await httpPostRequest(chunk) === true;
};

const file = new File([""], "myImage.png");
const chunks = [file.slice(0,4*1024*1024), file.slice(4*1024*1024)]

for(const chunk of chunks) {
    const isChunkUploaded = await uploadChunk(chunk);

    if(!isChunkUploaded) {
        break;
    }
}

So, the example above shows, how you can use async/await with a classic for...of loop.

ES2018 introduces async iteration for JavaScript, so it you’re familiar with:

const arr = [10, 20, 30];
const iterator = arr[Symbol.iterator]();
console.log(iterator.next()); // => {value: 10, done: false}
console.log(iterator.next()); // => {value: 20, done: false}
console.log(iterator.next()); // => {value: 30, done: false}
console.log(iterator.next()); // => {value: undefined, done: true}

Then you’re going to like a new iterator called Symbol.asyncIterator() that will allow you to work with promises, just like in the example below:

const myAsyncIterable = {
    async* [Symbol.asyncIterator]() {
        yield "hello";
        yield "async";
        yield "iteration!";
    }
};
(async () => {
    for await (const x of myAsyncIterable) {
        console.log(x);
        // expected output:
        // "hello"
        // "async"
        // "iteration!"
    }
})();

There is a short but very comprehensive article on the Asynchronous iterator on MDN so I strongly recommend to check that out 😉.

4. Promise.prototype.finally()

Well, if you’ve ever worked with try/catch which I believe you have, you may have heard, that there is a third option to the try/catch block called finally. What it basically does is it executes a piece of code disregarding whether there was exception or not, so for example

try {
    if(this->wasSuccessful()) {
        return true;
    }

    throw new Error("The operation was unsuccessful");
} catch(err)  {
    // => catch the error or do something
} finally {
    //does not matter if the code above example returns true or throws an error, this piece of code will be executed in both cases
}

So, if you understand the example above, you will understand this new ES2018 update in no time.

So basically when working with promises, your promise could have been either resolved or rejected. When you wanted to run a specific action after either a success or failure of the Promise, you had to execute the specific code two times, like at the example above:

showLoaders();

fetch("https://example.com")
    .then(() => {
        //call successful
        hideLoaders();
    })
    .catch(() => {
        //the call resulted in an error
        hideLoaders();
    });

Well, how likes to repeat himself? The answer is not so much people.

Therefore comes a new promise method .finally() that will allow you to run the code just single time, check out the example below:

showLoaders();

fetch("https://example.com")
    .then(() => {
        //call successful
    })
    .catch(() => {
        //the call resulted in an error
    }).finally(() => {
        hideLoaders();
    });

Useful, right? 😉

5. Object rest/spread operator

I will get back to ES2015 this time. You do remember the array spread operator, right? It is just an amazing way for example to copy, concat or extract data from arrays, for example:

const fruits = ["apple", "orange", "pear"];
const copiedArray = [...fruits];

const veggies = ["carrot", "califlower"];

const food = [...fruits, ...veggies];

Wonderful, is that right? 😎 

So, the same is from ES2018 possible with objects as well, so if you’ve ever needed to copy an object with Object.assign(), your live will become easier, since object copying will be done this way:

const myObject = {color: "red", "size: "A4"};
const clonedObject = {...myObject};

Wrap up

There you have it guys. A new version of JavaScript language called ES2018 or ES9 is here with really useful updates and for me personally the most useful will be object rest operator and regex updates.

What about you? Will there be a significant change in your daily life as well with these updates?

I am interested in your point of view so don’t be shy to share your thoughts below!

If you’d like to check out the older major JavaScript language updates, you can check them out in the links below:

One more things guys, liked this article, don’t forget to share it with people you like (or maybe also people you don’t like, maybe you’ll became friends! 😆 ).

Lastly, it is only matter of time till we see an interesting update in JavaScript as well, so if you be the first ones to know, subscribe to my newsletter right here, I am sending regularly industry news, best practises and tips for your JavaScript coding.

Anyways, thanks for reading and I’ll see you in the next article! 🤓

Yours in coding,

Ivan