11

I have a regex that is more or less used like this:

'(801) 555-1234'.match(/^(1[-. ]?)?\(?[0-9]{3}\)?[-. ]?[0-9]{3}[-. ]?[0-9]{4}$/)

For some reason this returns

["(801) 555-1234", undefined]

If I add the global flag to the regex (e.g. ...{4}$/g), the undefined value drops out and I get

["(801) 555-1234"]

I'd prefer not to use the g flag if it's not necessary (which it would seem to me it's not, since the regex begins with ^ and ends with $).

P.S. ignore the quality of the regex for it's purpose of matching phone numbers. It may not be ideal, but is from code I'm maintaining. Mostly I'm interested in the ^...$ and the presence/absence of the flag and the undefined value.

Why is undefined showing up, and why does the flag make the difference?

4 Answers 4

10

Here is a group:

/^(1[-. ]?)?

.match (without the /g flag) and .exec return groups as part of the array. If the group didn’t match, its value is set to undefined.

Get the first element:

'(801) 555-1234'.match(/^(1[-. ]?)?\(?[0-9]{3}\)?[-. ]?[0-9]{3}[-. ]?[0-9]{4}$/)[0]

If you really, really, really want the single-element array for some reason, you can make it non-capturing:

/^(?:1[-. ]?)?

However, at that point, you have this regular expression anchored to both the start and end of the string and aren’t extracting any information. In that case, it seems like you’re really looking for RegExp.prototype.test:

var PHONE_NUMBER = /^(1[-. ]?)?\(?[0-9]{3}\)?[-. ]?[0-9]{3}[-. ]?[0-9]{4}$/;
var isValid = PHONE_NUMBER.test('(801) 555-1234');
Sign up to request clarification or add additional context in comments.

2 Comments

Ah! that makes total sense now. The array elements reflect all capturing groups (whether they were optional or not). Since the first group didn't find a match the value of that match is undefined. Makes total sense now that you say it. Looking at the MDN example I see that the array will include both matches for the regex as a whole as well as matches to capturing groups. Thanks.
"If the group didn't match, its value is set to undefined" - but I wish the designers had decided that .groups should only contain the keys of groups that actually did match.
6

It's because your regex starts with that parenthesized group. The undefined in the result means that nothing matched that part.

When you add the "g" suffix, the behavior of the regex code changes a little, so the return value is different. The "g" ("global") suffix causes the routine to return all the matches of the whole regex; the groups are effectively ignored in that case. For example:

"hello world! nice day today!".match(/\w+/g)

would return an array like this:

["hello", "world", "nice", "day", "today"]

3 Comments

do you know details on how the behavior changes? that would be nice to know, although it's not entirely critical to understanding where the undefined came from (which you've answered well)
@jinglesthula thanks for asking - I meant to come back and add that because I needed to check the documentation to make sure I remembered correctly, but I forgot :) I'll update in a moment.
3

You have a captured subpattern: (1[-. ]?)?

It is optional.

In this case, the option is to not match it.

Thus, it is undefined.

Try using a non-capturing subpattern: (?:1[-. ]?)?

Comments

3

In Your Regex (1[-. ]?)? indicates

NODE                     EXPLANATION
--------------------------------------------------------------------------------
  (                        group and capture to \1 (optional
                           (matching the most amount possible)):
--------------------------------------------------------------------------------
  1                        '1'
--------------------------------------------------------------------------------
  [-. ]?                   any character of: '-', '.', ' '
                           (optional (matching the most amount
                            possible))
--------------------------------------------------------------------------------
  )?                       end of \1 (NOTE: because you are using a
                           quantifier on this capture, only the LAST
                           repetition of the captured pattern will be
                           stored in \1)

enter image description here

And Try (?:1[-. ]?)?

NODE                     EXPLANATION
--------------------------------------------------------------------------------
  (?:                      group, but do not capture (optional
                           (matching the most amount possible)):
--------------------------------------------------------------------------------
   1                       '1'
--------------------------------------------------------------------------------
  [-. ]?                   any character of: '-', '.', ' '
                           (optional (matching the most amount
                           possible))
--------------------------------------------------------------------------------
  )?                       end of grouping

enter image description here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.