Regular Expressions in JavaScript
Also Known As
JavaScript regex
RegExp
regular expression JS
TL;DR
JS regex syntax, flags (g, i, m, s, u, d), methods (test, match, matchAll, replace, split), and the critical differences from PHP's PCRE.
Explanation
JS regex: /pattern/flags or new RegExp(pattern, flags). Key methods: test() (returns boolean), match() (returns array or null), matchAll() (returns iterator of all matches — requires g flag), replace()/replaceAll() (string replacement), split() (split by pattern). Flags: g (global — all matches), i (case-insensitive), m (multiline — ^ and $ match line boundaries), s (dotAll — . matches newlines), u (Unicode — enables \u{1F600} and correct Unicode handling), d (indices — adds match index info). Named capture groups: (?<name>pattern). Lookahead: (?=) positive, (?!) negative.
Common Misconception
✗ JavaScript regex is the same as PHP PCRE — JS regex lacks some PCRE features (no lookbehind in older engines, no \K, different flag syntax), and the g flag with test() has a stateful lastIndex that causes surprising behaviour.
Why It Matters
The stateful g flag with RegExp.test() in a loop is a famous JS gotcha — test() advances lastIndex on each call, causing alternating true/false for a pattern that should always match.
Common Mistakes
- Using RegExp.test() with g flag in a loop — lastIndex advances causing false negatives.
- Not using the u flag for Unicode strings — \w does not match accented characters without u.
- match() without g flag returns only first match — use matchAll() for all matches.
- Not anchoring patterns — /cat/ matches concatenate, not just the word cat.
Code Examples
✗ Vulnerable
// Stateful g flag bug — alternating results:
const re = /hello/g; // g flag makes lastIndex stateful
console.log(re.test('hello world')); // true (lastIndex=5)
console.log(re.test('hello world')); // false (lastIndex=0 after miss)
console.log(re.test('hello world')); // true (lastIndex=5 again)
// match() only returns first:
'aaa'.match(/a/); // ['a'] — not all three!
✓ Fixed
// Avoid g flag with test() — or reset lastIndex:
const hasHello = /hello/.test('hello world'); // No g — safe
// matchAll for all matches:
const matches = [...'aaa'.matchAll(/a/g)]; // [{...}, {...}, {...}]
// Named capture groups:
const dateRe = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
const { groups: { year, month, day } } = '2026-03-16'.match(dateRe);
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
16 Mar 2026
Edited
22 Mar 2026
Views
17
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 0
No pings yet today
No pings yesterday
Amazonbot 7
Perplexity 2
Google 2
ChatGPT 2
Majestic 1
Ahrefs 1
Also referenced
How they use it
crawler 13
crawler_json 2
Related categories
⚡
DEV INTEL
Tools & Severity
🟡 Medium
⚙ Fix effort: Medium
⚡ Quick Fix
Add the /u flag to all regexes matching user text to enable Unicode mode; use named capture groups (?<year>\d{4}) for readable matches; test with online tools before production
📦 Applies To
javascript ES2015
web
cli
🔗 Prerequisites
🔍 Detection Hints
Regex without /u flag on user-input text with Unicode; regex ReDoS vulnerability exponential backtracking; no named capture groups in complex patterns
Auto-detectable:
✓ Yes
eslint
semgrep
⚠ Related Problems
🤖 AI Agent
Confidence: Medium
False Positives: Medium
✗ Manual fix
Fix: Medium
Context: Line
CWE-400