Yeison Daza
3 min read

ES2018 Part 1: RegExp Improvements

JavaScript keeps evolving as a language, and the features to be added this year have already been defined. Let’s take a detailed look at each one.

In January, the TC39 met and decided which proposals would reach stage 4 and therefore be included in ECMAScript 2018.

To cover each new feature in detail, we’re going to split this into a series of posts, and this is the first one.

Part 1: RegExp Improvements

Part 2: Rest/Spread Object and Promise.finally

Part 3: Async Iteration

If you’re interested in seeing all current proposals and their stages, you can check them out here.

Today we’re going to talk about the improvements to regular expressions.

Named Capture Groups

Currently, we can capture a regexp (regular expression) into groups and the result is an array. For example, if we want to capture a number separated by spaces:

//live:

const pattern = /(\d{3}).(\d{3}).(\d{4})/u

const number = pattern.exec('320 123 2312')

console.log(number) // [ "320 123 2312", "320", "123", "2312"]

This is pretty useful but not clear or readable enough. That’s why in ES2018, we can give each group a name, for example (?<numero>\d):

\\ live:

const pattern = /(?<indicator>\d{3}).(?<first>\d{3}).(?<second>\d{4})/u;

const number = pattern.exec('320 301 1239');

console.log(result.groups) \\ {indicator: '320', first: '301', second: '1239'}

As you can see, now we get an object where the keys match the names we assigned to the groups.

You can also use destructuring:

const {groups: { indicador, first, second}} = pattern.exec('320 301 1239');

Lookbehind Assertions

With Regex, we can have a pattern that must be matched but doesn’t appear in the result when evaluated. Currently, we can check that this pattern is met ahead of what we’re evaluating, for example:

// live:

const pattern = /\d+(?= pesos)/g

console.log(pattern.exec('12 pesos')) // ["12"]
console.log(pattern.exec('12')) // null

// La palabra pesos debe estar delante, pero no aparece en el resultado

In ES2018, this functionality has been added but for looking behind, using the syntax (?<=\ ). This means we can do something like:

// live:

const pattern = /(?<=\$)\d+/g

console.log(pattern.exec('$12')) // ["12"]
console.log(pattern.exec('12')) // null

// El patrón debe estar atrás para que se evalue correcto

We can also check that something is not preceded by a pattern:

// live:

const pattern = /(?<!\€)\d+/g

console.log(pattern.exec('$12')) // ["12"]

The s Flag (dotAll)

In regular expressions, the . matches any character, but it doesn’t include line terminators like \n. That’s why in ES2018 we have the new s flag, which lets us cover this case.

/Esta.Casa/u.test('Esta\nCasa'); // false

/Esta.Casa/su.test('Esta\nCasa'); // true

Unicode Property Escapes

The unicode standard assigns several properties to each symbol. Starting with ES2018, we’ll be able to access these properties inside regular expressions. This is only possible when using the u flag.

The syntax is /p{Script_name}. For example, if you want to search for number symbols, you can use \p{Decimal_Number}.

This works with any unicode property. I think this feature is incredible because of how readable it makes regular expressions.

Final Thoughts

Remember, after the massive changes included in ES6, only a few features will be added to the language each year. So don’t get scared or feel overwhelmed — you have a whole year to learn just a handful of new things.

If you want to use a proposal that hasn’t been officially included in the language yet, you can use babel.

Next time, we’ll talk about Spread/Rest Object and Promise.finally.