What is the meaning of “Object [RegExp String Iterator] {}” in NodeJs

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?

Answer

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 and Infinity.

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.)