String.prototype.match()
Two methods wearing one name: the g flag changes what you get back entirely. Both share the same trap — no match returns null, not an empty array.
Demo
With the g flag the result is a plain array of the whole matches — no index, no capture groups, just the text. The third case is the one that causes real bugs: when nothing matches you get null, NOT an empty array. Calling .length or .map on that throws, so every match call needs a guard or a ?? [] fallback. Without the g flag the shape changes completely: you would get a single match with its capture groups, its index and the original input attached as properties.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| regexp | RegExp | yes | The pattern. With the g flag you get every whole match and nothing else; without it you get one match with its capture groups, index and input attached. |
Return value
string[] | null — With /g, an array of the whole matches. Without it, an array-like holding the match plus its capture groups, index and input. NULL when nothing matches, either way.
Common patterns
const nums = s.match(/\d+/g) ?? [];
const [, year, month] = s.match(/(\d{4})-(\d{2})/) ?? [];
if (/\d/.test(s)) { }
Examples
Pitfalls
'abc'.match(/\d/g).length
('abc'.match(/\d/g) ?? []).length
'a1'.match(/(\w)(\d)/g)
'a1'.match(/(\w)(\d)/)
'a1 b2'.match(/(\w)(\d)/g)
[...'a1 b2'.matchAll(/(\w)(\d)/g)].map(m => m[1])
const RE = /a/g; RE.test("a"); RE.test("a")
const RE = /a/; RE.test("a"); RE.test("a")
When to use
- Extracting every occurrence of a pattern, with g
- Pulling capture groups out of a single match, without g
- Finding where a pattern matched, via the index property
- You only need a yes/no answer → RegExp.test
- You need groups for every match → matchAll
- The pattern is literal text → includes or indexOf
- You want to substitute → replace or replaceAll
Notes
FAQ
A legacy decision from ES3 that the language cannot change now. It is genuinely inconsistent — matchAll returns an empty iterator, and filter returns an empty array — so treat every match call as returning a nullable and add ?? [] by reflex.
const found = s.match(re) ?? [];