ECMAScript, often abbreviated as ES, serves as the standard on which JavaScript is based. The latest version of this standard is ES2018, also known as ES9. In this guide, we will explore the new features and upgrades introduced in ES2018.

Rest/Spread Properties

ES6 introduced the concept of the rest element for array destructuring and spread elements for spreading array elements. ES2018 extends this concept to objects.

Rest properties allow you to extract and assign the remaining properties of an object to a new object:

const { first, second, ...others } = { first: 1, second: 2, third: 3, fourth: 4, fifth: 5 };

Spread properties, on the other hand, enable you to create a new object by combining the properties of an existing object using the spread operator:

const items = { first, second, ...others };

Asynchronous Iteration

ES2018 introduces the for-await-of construct, which allows you to iterate over async iterable objects within a loop:

for await (const line of readLines(filePath)) {
    console.log(line);
}

Please note that for-await-of can only be used inside async functions, similar to the usage of await.

Promise.prototype.finally()

The finally() method is introduced in ES2018 to ensure a piece of code runs regardless of whether a promise is fulfilled or rejected. It is executed after the then() and catch() methods:

fetch('file.json')
    .then(data => data.json())
    .catch(error => console.error(error))
    .finally(() => console.log('finished'));

Regular Expression Improvements

ES2018 introduces several enhancements to regular expressions.

RegExp Lookbehind Assertions

Lookbehind assertions allow you to match a string based on what precedes it. Positive lookbehinds use ?<=, while negative lookbehinds use ?<!. For example:

/(?<=Roger) Waters/.test('Roger is my dog and Roger Waters is a famous musician'); // true
/(?<!Roger) Waters/.test('Roger is my dog and Roger Waters is a famous musician'); // false

Unicode Property Escapes

ES2018 introduces \p{...} and \P{...} to match Unicode character properties within regular expressions. These property escapes enable matching based on Unicode properties such as script, ASCII, digit, whitespace, emoji, and more. For example:

/^\p{Lowercase}$/u.test('h'); // true
/^\p{Uppercase}$/u.test('H'); // true

You can also match specific Unicode values by specifying the desired property. For instance:

/^\p{Emoji}+$/u.test('🙃🙃'); // true
/^\p{Script=Greek}+$/u.test('ελληνικά'); // true

For a complete list of available properties, refer to the official proposal.

Named Capturing Groups

ES2018 allows assigning names to capturing groups in regular expressions, providing a more structured way of accessing matched groups:

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

// Access captured groups using named properties
result.groups.year; // '2015'
result.groups.month; // '01'
result.groups.day; // '02'

The s Flag for Regular Expressions

The s flag, short for “single line,” enables the dot (.) metacharacter in regular expressions to match newline characters as well. Without this flag, dot matches any character except newline:

/hi.welcome/.test('hi\nwelcome'); // false
/hi.welcome/s.test('hi\nwelcome'); // true