Skip to content
Foxipa

Suggest an edit

Tell us what should be corrected, clarified, or improved. Submission will be connected to Foxipa’s contribution service later.

No information is sent anywhere yet. Your suggestion is only prepared in your browser.

Learning

JavaScript Regular Expressions

Learn ECMAScript regular-expression syntax, matching, captures, flags, lookarounds, Unicode modes, dynamic patterns, and stateful matching.

Levels: Advanced ~42 min read

Advanced

Regular expressions are a pattern language built into ECMAScript. They are useful for searching, validating, extracting, and transforming text, but their semantics are precise: metacharacters, quantifiers, captures, flags, Unicode modes, and state all affect the result.

This lesson builds from literal matching to structured patterns, then moves into captures, lookarounds, Unicode properties, `u`/`v`, dynamic patterns, and stateful matching. Treat a regular expression as executable code: make its intent explicit, test its boundaries, and choose ordinary string operations when they communicate the requirement more clearly.

Literal matching

Start with the smallest useful pattern: literal text.

Runnable example

Interactive Runnable example
Edit

Ready to run.

Quick check

What does `/cat/` match?

Character classes

A character class chooses one code unit or code point from a set or range, depending on the pattern mode. Negated classes use `[^...]`.

Runnable example

Interactive Runnable example
Edit

Ready to run.

Quick check

Which pattern matches one ASCII digit?

Quantifiers

Quantifiers control how many times the preceding atom may occur. `*`, `+`, `?`, and `{m,n}` express repetition; adding `?` can make a quantifier lazy.

Runnable example

Interactive Runnable example
Edit

Ready to run.

Quick check

Which quantifier means one or more?

Anchors and boundaries

Anchors constrain where a match can occur. `^` and `$` concern input boundaries, while `\b` and `\B` concern word boundaries.

Runnable example

Interactive Runnable example
Edit

Ready to run.

Quick check

Which pattern requires the entire string to be exactly `cat`?

Capturing groups

Parentheses group pattern structure and, by default, capture the text matched by the group. Non-capturing groups use `(?:...)` when you need grouping without a capture slot.

Runnable example

Interactive Runnable example
Edit

Ready to run.

Quick check

What is `match[0]` in a successful `exec()` result?

Named capturing groups

Named groups make captures self-describing with `(?<name>...)`. A successful match exposes them through `match.groups`.

Runnable example

Interactive Runnable example
Edit

Ready to run.

Quick check

Where are named captures exposed on a successful match?

Alternation and precedence

The `|` operator expresses alternatives. Group it when the alternative is part of a larger structure so precedence is explicit.

Runnable example

Interactive Runnable example
Edit

Ready to run.

Quick check

Why is `^(cat|dog)$` clearer than `^cat|dog$` for exactly one whole word?

Flags and matching modes

Flags modify matching behavior. Common flags include `i` for case-insensitive matching, `m` for line anchors, `s` for dot-all, `g` for global matching, `u` for Unicode-aware patterns, and `v` for Unicode sets.

Runnable example

Interactive Runnable example
Edit

Ready to run.

Quick check

Which flag makes `.` also match line terminators?

Match indices with the `d` flag

The `d` flag asks a RegExp to expose the start and end positions of the overall match and each participating capture. The resulting match object has an `indices` property; without `d`, that property is absent. `RegExp.prototype.hasIndices` reports whether the flag was present.

Runnable example

Interactive Runnable example
Edit

Ready to run.

Quick check

What does the `d` flag add to a successful RegExp match?

Captures get their own ranges

Interactive Runnable example
Edit

Ready to run.

Quick check

Where is the range for a named capture such as `word` available?

The range pairs are `[start, end]`, with the end position exclusive. The first pair describes the complete match, and subsequent pairs correspond to capturing groups. A capture that did not participate has no range, so its corresponding entry is `undefined`.

Unmatched captures stay undefined

Interactive Runnable example
Edit

Ready to run.

Quick check

If an alternative capture did not participate, what does its indices entry contain?

`d` works with normal RegExp result-producing methods

Interactive Runnable example
Edit

Ready to run.

Quick check

What does `/(?<value>\d+)/d.hasIndices` return?

The indices are positions in the matched input, not substrings. This makes `d` useful when later code needs exact source ranges—for example, to annotate, slice, highlight, or map captures back to the original string. The RegExp still returns its normal captured strings; `indices` is additional range information.

Unicode-aware indexing

Interactive Runnable example
Edit

Ready to run.

Quick check

Why can `/^(.)/d` and `/^(.)/du` report different ranges for the same supplementary character?

Do not confuse these indices with byte offsets. They are positions in the ECMAScript string model, with Unicode-aware matching applying the specification’s code-point-aware conversion where required. The exact range behavior matters when text contains supplementary Unicode characters.

String regex methods

String methods delegate to regular expressions through well-known symbols. `search`, `match`, `matchAll`, `replace`, `replaceAll`, and `split` serve different jobs.

Runnable example

Interactive Runnable example
Edit

Ready to run.

Quick check

Which method returns an index rather than match text?

Global matches and matchAll

`match()` has different result shapes depending on flags. `matchAll()` provides an iterator of match results and requires a global or sticky pattern.

Runnable example

Interactive Runnable example
Edit

Ready to run.

Quick check

Why is `g` useful with `matchAll()`?

Lookahead and lookbehind

Lookarounds assert context without consuming that context. Positive and negative lookahead use `(?=...)` and `(?!...)`; lookbehind uses `(?<=...)` and `(?<!...)`.

Runnable example

Interactive Runnable example
Edit

Ready to run.

Quick check

Which construct checks what follows without consuming it?

Unicode-aware patterns

The `u` flag enables Unicode-aware RegExp semantics. It matters for supplementary code points, Unicode escapes, and character classes.

Runnable example

Interactive Runnable example
Edit

Ready to run.

Quick check

Which pattern treats the emoji as one Unicode code point for `.`?

Unicode property escapes

Unicode property escapes such as `\p{Letter}` and `\p{Number}` require Unicode mode. They let patterns describe Unicode properties instead of hard-coded ranges.

Runnable example

Interactive Runnable example
Edit

Ready to run.

Quick check

What does `\p{Letter}` describe in Unicode mode?

Unicode sets with v

The `v` flag enables Unicode sets mode in addition to full Unicode matching. It supports richer character-set operations and string properties defined by the current specification.

Runnable example

Interactive Runnable example
Edit

Ready to run.

Quick check

Which flag enables Unicode sets mode?

Dot and escapes

The dot is a wildcard for a single input element under the pattern mode, while backslashes introduce escapes such as `\d`, `\s`, and escaped metacharacters. The `s` flag changes dot behavior by allowing line terminators.

Runnable example

Interactive Runnable example
Edit

Ready to run.

Quick check

Which pattern treats the dot as a literal period?

Dynamic patterns and escaping

Use `new RegExp()` when the pattern must be assembled at runtime. Escape user-provided text before embedding it in a pattern; string escaping and RegExp escaping are separate concerns.

Runnable example

Interactive Runnable example
Edit

Ready to run.

Quick check

When constructing a pattern from variable text, what must you consider?

Stateful lastIndex

Global and sticky regular expressions can maintain matching state through `lastIndex`. Reusing a stateful RegExp requires deliberate handling.

Runnable example

Interactive Runnable example
Edit

Ready to run.

Quick check

Why should reusable `/g` or `/y` RegExp objects be treated as stateful?

Designing maintainable regexes

A regex is code: keep it readable, test edge cases, choose the narrowest correct pattern, and avoid using a complex expression where ordinary string logic is clearer.

Runnable example

Interactive Runnable example
Edit

Ready to run.

Quick check

What is the strongest maintainability rule for a complex pattern?

RegExp.escape() — literal text for a pattern

RegExp.escape() produces RegExp pattern text that treats supplied input as literal content. It handles the escaping rules required when data, rather than hand-written pattern syntax, is inserted into a regular expression.

Interactive Runnable example
Edit

Ready to run.

Quick check

What problem does RegExp.escape() solve?

const pattern = new RegExp(RegExp.escape("a+b"));
document.querySelector("#output").textContent = String(pattern.test("a+b"));

Inline RegExp modifiers — local flag changes

Inline RegExp modifiers enable or disable selected regular-expression flags for a nested pattern region. They provide local control inside one pattern instead of forcing one flag setting across the entire expression.

Interactive Runnable example
Edit

Ready to run.

Quick check

What do inline RegExp modifiers control?

try { const pattern = new RegExp('a(?i:b)c'); document.querySelector("#output").textContent = String(pattern.test("aBc")); } catch { document.querySelector("#output").textContent = "Feature unavailable in this runtime."; }
Was this page helpful?

Mark this learning resource complete to track your learning progress.