String.prototype.match()
Matches a string against a regular expression and returns the results, or null.
match(regexp)- Added in JavaScript ES1
Parameters
| Parameter | Type | Description |
|---|---|---|
$regexpoptional | RegExp | { [Symbol.match](): any } | A regular expression object, or any object with a Symbol.match method. A value that is neither is implicitly converted with new RegExp(regexp). Calling match() with no argument is equivalent to match(/(?:)/) and returns [""]. |
Return value
Array<string> | nullAn array whose contents depend on the presence or absence of the global (g) flag, or null if no matches are found. With g, all full matches are returned and capturing groups are omitted; without g, only the first match and its capturing groups are returned, identical to RegExp.prototype.exec().
Changelog
- PHP ES2018Named capture groups added, exposed on the result's groups property when the regex is not global.
match() is really two methods wearing one name, and the g flag decides which one you get.
Without g: one rich result
You get an array-like result identical to RegExp.prototype.exec(): element 0 is the whole match, elements 1..n are the capture groups, plus index, input and groups properties. This is the form to use when you want to pull data out of one match.
With g: many plain strings
You get a flat array of every full match, with no capture groups, no index and no groups object. This is the form to use when you only need the matched text and there is nothing to destructure. If you need groups for every match, use matchAll() instead.
Null is not an empty array
When nothing matches, match() returns null, not []. Chaining .length or .map() onto the result therefore throws. Guard it, or use str.match(re) ?? []. For a simple yes/no question, re.test(str) is cheaper and returns a boolean; for a position, use search().
Example
When to use it
- Pull the version numbers out of a release string
- Extract a named capture group from a log line
- Collect every hashtag in a post with a /g/ regex
- Validate a format and read its parts in one step
Frequently asked questions
Why does String.match return null?
Because no part of the string matched the regular expression — match() signals failure with null rather than an empty array. Write str.match(re) ?? [] before calling .length or .map(), or use re.test(str) when you only need a boolean.
Why are my capture groups missing from match results?
Because the regex has the global g flag, which makes match() return a flat array of full matches and discard groups, index and input. Drop the g flag to get one rich result, or use matchAll() to get groups for every match.
What is the difference between match and matchAll?
match() with the g flag returns a plain array of matched strings, while matchAll() returns an iterator of full exec-style results including capture groups, index and groups for every match. matchAll() also requires the g flag, whereas match() merely changes shape without it.
More examples
Named groups and destructuring
The groups object exposes each named capture by name, printing ERROR and "disk full". The last lines show the defensive pattern: ?? {} plus a default for groups means a non-matching line yields undefined instead of throwing.
const line = "2026-08-31 ERROR disk full";
const re = /^(?<date>\S+) (?<level>\w+) (?<msg>.+)$/;
const m = line.match(re);
console.log(m.groups.level);
console.log(m.groups.msg);
const { groups: { date } = {} } = line.match(re) ?? {};
console.log(date);Why /g/ loses your capture groups
The non-global call returns ["a=1","a","1", …] with the groups intact but only the first pair. The global call returns ["a=1","b=2","c=3"] — every match but no groups. matchAll gives you all three pairs with groups, which is almost always what you actually wanted.
const csv = "a=1,b=2,c=3";
console.log(csv.match(/(\w)=(\d)/)); // groups present
console.log(csv.match(/(\w)=(\d)/g)); // groups gone
// matchAll keeps both
console.log([...csv.matchAll(/(\w)=(\d)/g)].map((m) => [m[1], m[2]]));Counting matches safely
The counts are 2, 0 and 3. Without the ?? [] the middle call would throw, because match returns null. The final line is the reminder that if you only need a boolean, test() avoids allocating a result array at all.
function count(text, re) {
return (text.match(re) ?? []).length;
}
console.log(count("a b c", /\s/g));
console.log(count("abc", /\s/g));
console.log(count("aaa", /a/g));
// test() is cheaper for a yes/no answer
console.log(/\d/.test("abc"));
Discussion