Every pattern you’ve written so far matches each piece exactly once. Quantifiers change that: they attach to the character, class, or group immediately before them and say how many times it’s allowed to repeat.
The three symbols: *, +, ?
| Quantifier | Meaning | Example | Matches |
|---|---|---|---|
* |
Zero or more | ab*c |
ac, abc, abbbc, … |
+ |
One or more | ab+c |
abc, abbbc, … but not ac |
? |
Zero or one | ab?c |
ac or abc only |
/ab*c/.test("ac"); // true — zero b's is fine
/ab+c/.test("ac"); // false — + requires at least one b
/ab?c/.test("abbc"); // false — ? allows at most one b
The demo shows ab*c matching all three variants — ac (zero b’s), abc (one b), and abbbc (three b’s) — because * places no upper bound on how many b characters can appear.
Exact counts with {n}, {n,}, and {n,m}
Curly-brace quantifiers give you precise control instead of the fixed “zero/one/many” meanings above:
{n}— exactlynrepetitions{n,}—nor more repetitions, no upper limit{n,m}— betweennandmrepetitions, inclusive
/^\d{3}$/.test("42"); // false — only 2 digits
/^\d{3}$/.test("425"); // true — exactly 3 digits
/^\d{3,}$/.test("42599"); // true — 3 or more is fine
/^\d{2,4}$/.test("42599"); // false — 5 digits is too many
Watch the last group in the demo carefully: against "12345", the pattern \d{2,4} matches 1234 — the engine grabs as many digits as it’s allowed (up to 4) starting from the first available position, leaving the trailing 5 as a separate, too-short leftover that doesn’t get matched on its own since a lone digit doesn’t satisfy {2,4}.
Tip
*, +, and ? are really just shorthand for common {n,m} ranges: * is {0,}, + is {1,}, and ? is {0,1}. They’re written as symbols purely because they come up so often.
Greedy by default
All the quantifiers above are greedy by default — they try to match as much as possible first, and only give back characters (backtrack) if that’s the only way for the rest of the pattern to succeed. That’s why \d{2,4} grabbed 4 digits instead of stopping at 2. Every quantifier also has a lazy counterpart (written with a trailing ?, like *? or {2,4}?) that matches as little as possible instead — but that’s a big enough topic that it gets its own lesson shortly. For now, just remember: by default, more is preferred over less.
Try it yourself
Using the demo above, change the pattern from \d{2,4} to \d{2,4}? (add the lazy modifier) and see how the matches against "12345" change.
What should happen
With the lazy version, the match against "12345" becomes 12 instead of 1234 — the engine now stops as soon as the minimum (2 digits) is satisfied, rather than grabbing the maximum it’s allowed. Same pattern, same input, opposite strategy — that’s greedy vs. lazy in a nutshell, and you’ll dig into it properly in an upcoming lesson.
What’s next
Quantifiers so far have only applied to a single character or class. The next lesson introduces groups — parentheses (...) — which let you apply a quantifier to a whole sequence of characters at once, like (ab)+.