I've been trying use matchAll
in node.js, but when I run the code and log the return value it only shows Object [RegExp String Iterator] {}
.
Could you help me to understand why this is the case?
CodePudding user response:
Be mindful of the types of things you are working with.
To quote the docs for String.prototype.matchAll
:
The
matchAll()
method returns an iterator of all results matching a string against a regular expression, including capturing groups.
(Emphasis mine.)
So, you get an iterator. What is an iterator? Well, the docs say:
In JavaScript an iterator is an object which defines a sequence and potentially a return value upon its termination.
[...]
While it is easy to imagine that all iterators could be expressed as arrays, this is not true. Arrays must be allocated in their entirety, but iterators are consumed only as necessary. Because of this, iterators can express sequences of unlimited size, such as the range of integers between
0
andInfinity
.
So, matchAll
will only do the actual work of finding the next match when you ask for it, by asking for next value of the iterator, and the amount of state that has to be kept won't increase that much with a longer string because not all matches have to be remembered at once. That's the beauty of iterators (and their opposite part, generators).
This is also why you won't see all the results in your console when printing the iterator - otherwise, a matchAll
on a very very large string would cause a long delay and high CPU usage when its return value is merely logged to the console, which wouldn't make sense.
You can use the result of matchAll
in a for of
loop, which will look for the next match every time the loop repeats:
for (const match of 'abcde'.matchAll(/./g)) {
console.log(match)
}
// Prints 5 times something like ['a', index: 0, input: 'abcde', groups: undefined ]
Or, if you are willing to forgo the benefit of on-demand matching, you can extract all values from the iterator at once and fit them into an array using either spread syntax or Array.from
:
const allMatches = [...'abcde'.matchAll(/./g)]
// - or -
const allMatches = Array.from('abcde'.matchAll(/./g))
(In fact, the spread syntax is shown in the example at the very top of the matchAll
docs too.)