← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

Regular Expressions in JavaScript

javascript ES2015 Intermediate

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);

Added 16 Mar 2026
Edited 22 Mar 2026
Views 17
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings F 0 pings S 2 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 2 pings S 0 pings M 0 pings T 0 pings W 2 pings T 0 pings F 1 ping S 2 pings S 0 pings M 0 pings T 0 pings W 1 ping T 0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S
No pings yet today
No pings yesterday
Amazonbot 7 Perplexity 2 Google 2 ChatGPT 2 Majestic 1 Ahrefs 1
crawler 13 crawler_json 2
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

✓ schema.org compliant