0

When using a Regular Expression to pull matches from a string with matchAll(), the resulting Iterable Object that is spread into an Array object with the spread operator shows nested arrays with multiple members.

const regexUpperCaseTo = /(?<=\x2d|\x5f)[a-zA-Z0-9]/g;
const testVar1 = [...str.matchAll(regexUpperCaseTo)]

when we print out testVar1 it shows:

[
  [ 's', index: 4, input: 'the-stealth-warrior', groups: undefined ],
  [ 'w', index: 12, input: 'the-stealth-warrior', groups: undefined ]
]

Similarly, being an iterable object, we can use a for/of loop to iterate over each element of the returned array.

[ 's', index: 4, input: 'the-stealth-warrior', groups: undefined ]
[ 'w', index: 12, input: 'the-stealth-warrior', groups: undefined ]

However, once we test each member for length, it returns 1.

console.log(testVar1.forEach(x => console.log(x.length)))

and in addition to this, when we try to access the members of each array beyond the 0th member it returns undefined.

What is going on here that each member returned only seems to consist of the first element?

Greg Iven
  • 171
  • 2
  • 10
  • 1
    What do you expect the length to be? – Barmar Oct 14 '20 at 21:45
  • @JaromandaX That would be `x[0].length` – Barmar Oct 14 '20 at 21:45
  • 2
    Named properties aren't counted in the length of an array, only properties with numeric indexes. – Barmar Oct 14 '20 at 21:46
  • 2
    The array returned by matching a regexp contains one element for the whole match, and then elements for all the capture groups. Your regexp has no capture groups, so the only element is the full match. – Barmar Oct 14 '20 at 21:47
  • The inner Array is a Array length 1 (with value "s" for example), but has groups, index and input properties on that array, but the array is still length 1 ... e.g. try `console.log(x.length, x.input, x.index, x.groups)` in your forEach – Jaromanda X Oct 14 '20 at 21:52
  • The arrays returned by the iterator are just like the array returned by `str.match()`. – Barmar Oct 14 '20 at 21:53
  • @JaromandaX ahhh ok, i see the resulting array is just the properties being returned as an array, but each match returns an object. I'm still trying to understand why the first element has a property name of '0' but each succeeding object in the array has a property name? – Greg Iven Oct 14 '20 at 21:58
  • See how the output has `index:` and `input:` ... i.e. they are properties (the `:` gives that away) - chromes console output is misleading, index, input and group are not elements of the array, they are properties of that array - try `console.log(testVar1);` in firefox, and you'll see – Jaromanda X Oct 14 '20 at 22:01
  • An Array is an object, and just like any object your can add properties to it as you like - as I said, in your forEach loop, if you log `x.input`, `x.index` and `x.groups` you'll see those property values – Jaromanda X Oct 14 '20 at 22:02
  • Right, but then why isnt the first element in the 'array' preceded by a '0:' as such --> [ 0: 's', index: 4, input: 'the-stealth-warrior', groups: undefined ] ? – Greg Iven Oct 14 '20 at 22:03

1 Answers1

0

This is normal (and has nothing to do with the iterator that matchAll returns). Each match - just like those returned from .match() and .exec() - is an array object with the whole match and the captured groups as elements.

Additionally, the array has some special properties like .index, .input and (since ES2018) .groups. See also Return positions of a regex match() in Javascript? or Contents of a RegExp match.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375