I question the utility of matching this type of expression. Anyway, I suspect that this has something to do with what happens when you match without an argument (str.match()) or with an empty string (str.match("")). In both these case the output is [""].
The reason for 12 matches with your regular expression is that it matches every character in the string as well as the empty string.
I have found sites like regex101 very useful in understanding how regular expressions work.
Thanks for the link - that’s a really useful site. I’m still not sure I get it, though. If I look at the output from https://regex101.com with test string 1 2 3 and regex /\d?/g you can see:
match 1 : 0 - 1 "1"
match 2 : 1 - 1 ""
match 3 : 2 - 3 "2"
.
.
match 6 : 5 - 5 ""
0 - 1 seems to be the start and end ‘lines’ of each match - these are the places you can put the cursor and it always seems to include the end one ( 5 - 5 in this case ) . It’s matching the digits but when they aren’t there, it’s matching anyway and returning the cursor position (an empty string?). It does this one last time at the end, even though there’s no character left to come.
I only touch regex when I have to and I always wash my hands (brain) afterwards. For anyone else wondering, the ‘right’ way to do this is with console.log(str.match(/\d+/g)).