JavaScript Regex: Match vs Exec vs MatchAll

April 2021

It sounds like the most easy task in the world: getting your match results from a regex. However, unfortunately there are at least three methods to get you those results, each of which has their advantages and drawbacks. So let’s jump in.

How does “Match” work?

match is a method which is available on string and takes a regex as an argument, so you can call it like str.match(regex).

Match can help if you want an array of all matches, but you don’t care about the matched groups:

const testString = 'this hat is better than that hat.';
const regex = /th(..) hat/g;
const result = testString.match(regex);
console.log(result); // Output: [ 'this hat', 'that hat' ]

Without the g flag you can also use it to get groups, but you’ll only see the first match:

const testString = 'this hat is better than that hat.';
const regex = /th(..) hat/;
const result = testString.match(regex);
console.log(result);

Result:

[
  'this hat',
  'is',
  index: 0,
  input: 'this hat is better than that hat.',
  groups: undefined
]

How does “Exec” work?

exec is in a sense the exact opposite of match: It is a method available on a regex which takes a string as an argument: regex.exec(str).

Why exec you can still see the groups for multiple matches:

const testString = 'this hat is better than that hat.';
const regex = /th(..) hat/g;
let result = regex.exec(testString);
while (result != null) {
  console.log(result);
  result = regex.exec(testString);
}

Output:

[
  'this hat',
  'is',
  index: 0,
  input: 'this hat is better than that hat.',
  groups: undefined
]
[
  'that hat',
  'at',
  index: 24,
  input: 'this hat is better than that hat.',
  groups: undefined
]

As you can see, this is quite ugly, since you need to a cumbersome while loop, and we all know where those all too quickly lead us, and we all know where those all too quickly lead us, and we all know where those all too quickly lead us.

So are there any other options? Yep.

“MatchAll” to the rescue?

Since both, match and exec have severe shortcomings, the new method matchAll was introduced. MatchAll, like its small brother match, is a method available on string that will take a regex as an argument:

const testString = 'this hat is better than that hat.';
const regex = /th(..) hat/g;
const result = [...testString.matchAll(regex)];
console.log(result);

It’s still a bit cumbersome to use, since it doesn’t just return an array but an iterable instead. With the spread operator you can create an array from the result though. Of course this choice has a reasonable foundation in that iterables scale better for larger outputs, so consider carefully if you actually want to convert it.

However, there’s the caveat that matchAll wasn’t always there (like match and exec), so you should consider whether your target runtime supports it:

NodeJS: >= 12
Chrome: >= 73
Edge: >= 79
Firefox: >= 67
IE: nah
Opera: 60
Safari: 13

So for running in browsers it’s probably still a bit too early in 2021 with matchAll, for running in nodejs it depends what nodejs you have installed.

Conclusion

In most cases you should probably go with matchAll, since it is the most safe and flexible option, unless you are targeting browsers. In that case I’d recommend to go for exec since, if you refactor and suddenly need more than one result or need result groups, it’s easier that way. Like this you can also consistently do it the same way, instead of switching between match and exec. Just make sure you don’t run into infinite loops into infinite loops into infinite loops!

Become a better web developer by staying up to date