Monday, 30 July, 2018 UTC


Summary

This article will give you an overview on the new features of ES2018.
First, we will discuss the new features of ES2018. Then you will learn what you need to do to start using them today.
You may want to try out the code examples in your browser. Just open the developer tools of Google Chrome. If you are using version 66 or higher, you are golden when it comes to ES2018 support.
The proposals are not yet fully implemented. You can find the current compatibility table on kangax.github.io.

Spread and Rest for object properties

The spread operator and rest parameters have been a popular addition in ES2015. You could spread arrays to comma separated values, and you could also add a rest parameter at the end of function argument lists to deal with a variable number of arguments.
Let’s see the same concept applied for objects:
let book = {
    author: 'Zsolt Nagy',
    title: 'The Developer\'s Edge',
    website: 'devcareermastery.com',
    chapters: 8
}
We can now create an destructuring expression, where we match a couple of properties, and we gather the rest of the properties in the bookData object reference.
let { chapters, website, ...bookData } = book
Once we create this assignment, the chapters numeric field is moved into the chapters variable, website will hold the string 'devcareermastery.com'. The rest of the fields are moved into the bookData object:
> bookData
{author: "Zsolt Nagy", title: "The Developer's Edge"}
This is why the ...bookData is called the rest property. It collects the fields not matched before.
The rest property for objects works in the same way as the rest parameter for arrays. Destructuring works in the exact same way as with arrays too.
Similarly to rest parameters, we can use rest properties to make a shallow copy of an object. For reference, check out my article cloning objects in JavaScript
let clonedBook = { ...book };
You can also add more fields to an object on top of cloning the existing fields.
let extendedBook = {
    pages: 250,
    ...clonedBook
}

Asynchronous iterators and generators

In ES2015, the iterator interface was introduced. The iterator interface is based on a well known symbol, Symbol.iterator. An iterable object has a method under the key Symbol.iterator. If you call this method, you create an iterator out of the iterable.
Three years later, the sequel to the iterable interface chapter in JavaScript arrived: the ES2018 asynchronous iterator. The asynchronous iterable interface specifies the implementation of a function under the key Symbol.asyncIterator to create an iterator out of an iterable.
Asynchronous iterators have a next method that returns a { value, done } object. value is the next value of the asynchronous operation, while done is a boolean signalling status.
The tc39 proposal contains an example that has been spread as the default description of how to formulate an async iteration.
for await (const line of readLines(filePath)) {
  console.log(line);
}
We will implement readLines soon.
Notice the for and await keywords next to each other. This is part the for..await..of loop, which iterates on an asynchronous function or asynchronous generator function.
The readLines function is an asynchronous generator function. We await for each value returned by this asynchronous generator, and execute the loop body on it.
The tc39 proposal example implementation of readLine generator function is as follows:
async function* readLines(path) {
  let file = await fileOpen(path);

  try {
    while (!file.EOF) {
      yield await file.readLine();
    }
  } finally {
    await file.close();
  }
}
As you can see, each yielded value has an await operator after it to indicate the asynchronous nature of the result. The asynchronous generator object returned by the asynchronous generator function has a Symbol.asyncIterator function member:
let asyncGenerator = readLines( path );
let asyncIterator = asyncGenerator[Symbol.asyncIterator]();

let promise = asyncIterator.next();
The async iterator can then be used for iteration in the for..await..of operator.
Async iterators have a next method that returns a promise. This promise is unwrapped by the for..await..of operator.

Promise finally

Back when I wrote ES6 in Practice, I was really curious why there was no finally in a then, catch chain. I came up with a false justification that maybe, all we need, is just then and catch. The rest is syntactic sugar. This is true to some extent, because we can perform the cleanup activities inside the then and catch callbacks.
It seems though, other people raised the same question, and a proposal got accepted to include a cleanup branch called finally:
new Promise( reject, resolve )
    .then( result => { ... } )
    .then( result => { ... } )
    .catch( error => { ... } )
    .finally( ()  => { /* cleanup */ } );

ES2018 Regular expression features

There are four updates to ES2018 regular expressions:
  • named capture groups
  • lookbehind assertions
  • dotAll flag
  • unicode property escapes
I wrote a blog post on ES2018 regular expressions already. Check out the description there.
If you want to learn more about regular expressions in JavaScript, check out my course, The JavaScript Regular Expression Launchpad. To get the maximum discount Udemy can offer, click the above link.

Template Literal Revision

This update is a bit intriguing, because we don’t tend to write tagged template literals every day.
If you want to understand tagged templates and template literals on a deeper level, check out my article on Strings and Template Literals.
Let’s see what the update is all about.
In a tagged template, your hands were tied in ES6 in some tiny edge cases. Some character sequences after a backslash were not allowed. Your code could not start a \u unicode escape, or a \x hexadecimal, or \0, \1, … octal number escape.
For instance, \xzsolt is now allowed in a tagged template even though zsolt is not a valid hexadecimal number.
I am sure you have an old browser at hand. I have one called Microsoft Edge. Let me execute an invalid tagged template there:
> String.raw`\xzsolt`
Expected hexadecimal digit
If you execute the same tagged template in your latest Google Chrome, the template literal is processed, and the '\xzsolt' string is returned.
If you want more details on the full revision, check out the tc39 proposal draft.

Can I use the features already?

Check out this compatibility table.
If you use JavaScript on client side, chances are, you want to support other browsers than the recent versions of Google Chrome. Therefore, I encourage you to use Babel to provide compatibility via transpilation.
If you are using JavaScript on the server, you are in control of the Node version you are using. Even though you cannot use all the features yet, be aware of them.

Summary

After the major ES2015 update and the very useful ES2017 additions, ES2018 provided yet another reason to keep believing that the developer experience provided by JavaScript is continuously improving.
Before I knew about the finally clause of promises, I even wrote in my book ES6 in Practice that it would be logical to have a finally clause.