cf.completefrontendCode editorOpen lab
THE JAVASCRIPT FIELD GUIDE

Patterns & flags

Learn JavaScript regular expressions from zero: create patterns, choose flags, read matches, and use test, exec, matchAll, and replace safely.

By the end, you can
  • 01
    Create regular expressionsChoose a literal or new RegExp() and know when string escaping matters.
  • 02
    Read search resultsUse flags, test(), exec(), match objects, groups, and indices without being surprised by lastIndex.
  • 03
    Use string helpersApply regexes with match, matchAll, replace, replaceAll, search, and split in practical text tasks.

Patterns for text

Strings answer exact questions: does this text include cat? Regular expressions answer pattern questions: is there a hashtag, a date-shaped piece, or a word no matter how it is capitalized? They are part of JavaScript, so every modern browser can use them with ordinary strings.

Definition

A regular expression, or regex, is a RegExp object that describes a pattern to search for in text. Flags are single-letter options that change how the search behaves.

Real-life analogyA recipe card for finding text

A recipe card says what to look for and how to handle it. A regex is similar: the pattern lists the text shape, and the flags set options for the search.

In real life: Ingredients to look for
In JavaScript: Pattern pieces such as cat or a date shape
In real life: Cooking options
In JavaScript: Flags such as i for ignore case or g for global
In real life: Taste and adjust
In JavaScript: Run test, exec, or a string method and inspect the result

Where the analogy stops: A recipe produces food; a regex only describes text. It does not understand meaning, grammar, or nested languages unless your pattern says exactly how.

This lesson builds on strings, string methods, template literals, and Unicode & strings. We will use tiny character patterns like [A-Za-z] and \d, but the next lessons teach character classes, quantifiers, groups, anchors, and performance in depth.

Literals vs new RegExp()

STEP THROUGH

JavaScript has two creation forms. A regex literal puts the pattern between slashes, like /cat/i. The constructor receives strings, like new RegExp("cat", "i"). Use a literal when the pattern is fixed. Use the constructor when the pattern or flags come from a variable.

Literal vs constructor replay
Step 0 of 6Ready
Your turn: follow the blue line

Step through two ways to create a regular expression. The literal is fixed in the code; the constructor can use a variable.

Running in
  1. script
Next: line 1
Click the blue line to take the next stepPop out in the code editor (opens in a new tab)JavaScript
const animal = "dog";const fromText = new RegExp(animal, "i"); console.log(literal.test("CAT"));console.log(fromText.test("hot dog"));console.log(fromText.source);
CallStoreChangeResultRun = next line. Ran = already executed.
Recent returnsNothing yet. Start with the blue line.
A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.

Constructor strings have one extra rule: the JavaScript string parser sees backslashes before the regex parser does. A digit pattern is /\d+/ as a literal, but new RegExp("\\d+") as a constructor string.

Escaping text before new RegExp()Pop out in the code editor (opens in a new tab)JavaScript
const userText = "a.b";const unsafe = new RegExp(userText);const safe = new RegExp(userText.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")); console.log(unsafe.test("axb"));console.log(safe.test("axb"));console.log(safe.test("a.b"));
Building from variables safely

If text came from a learner, a search box, or an API, escape it before putting it in a regex. Modern browsers document RegExp.escape(userText) for this job; the Node 22 test runtime for this site does not have it yet, so the runnable example uses a small helper. The Character classes & sets lesson covers escaping and RegExp.escape in depth.

Flags change the search

8 FLAGS

Flags sit after a literal, /cat/gi, or in the constructor’s second argument, new RegExp("cat", "gi"). Think of them as switches on the regex object.

JavaScript regex flags at a glance
FlagNameFirst mental model
gGlobalFind every match and update lastIndex between searches.
iIgnore caseTreat cat, CAT, and Cat as the same letters.
mMultilineLet ^ and $ work at line breaks, not just the whole string edges.
sDot allLet . match line breaks too.
uUnicodeRead code points correctly, such as one emoji with ^.$.
vUnicode setsTurns on newer Unicode set syntax; the next lesson covers set operations.
yStickyMatch exactly at lastIndex, useful for tokenizers.
dIndicesAdd an indices array showing [start, end] spans for matches and groups.
One small example for each flagPop out in the code editor (opens in a new tab)JavaScript
console.log(/cat/g.test("cat cat"));console.log(/cat/i.test("CAT"));console.log(/^cat/m.test("dog\ncat"));console.log(/a.b/s.test("a\nb"));console.log(/^.$/u.test("😀"));console.log(/^[\p{Letter}&&[A-F]]$/v.test("D"));const sticky = /cat/y;sticky.lastIndex = 4;console.log(sticky.test("one cat"));const withIndices = /ID-(\d+)/d.exec("ID-42");console.log(withIndices.indices[1].join("-"));

This is only the overview. m connects to anchors, v connects to Unicode set operations, and d becomes more powerful when you learn groups. Here you just need to recognize what each switch changes.

test(), exec(), and the lastIndex trap

STATEFUL

Use test() for a yes/no answer. Use exec() when you need details about the match. Both methods are simple until you reuse a regex with g or y. Those flags make the regex remember lastIndex, the next place to search.

The g flag and lastIndex trap
Step 0 of 10Ready
Your turn: follow the blue line

Global and sticky regexes are stateful. Step through repeated test() calls and watch lastIndex change.

Running in
  1. script
Next: line 1
Click the blue line to take the next stepPop out in the code editor (opens in a new tab)JavaScript
const text = "cat cat"; console.log(word.test(text));console.log(word.lastIndex);console.log(word.test(text));console.log(word.lastIndex);console.log(word.test(text));console.log(word.lastIndex);word.lastIndex = 0;console.log(word.test(text));
CallStoreChangeResultRun = next line. Ran = already executed.
Recent returnsNothing yet. Start with the blue line.
A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.
Choosing a regex API
QuestionGood first choiceWhat to watch
Need a yes/no answerregex.test(text)Returns a boolean; beware g or y state on reused regexes.
Need the first match detailsregex.exec(text)Returns one match object with index, input, groups, and maybe indices.
Need simple string resultstext.match(regex)With g, returns matched strings. Without g, returns one match object.
Need all match objectstext.matchAll(regex)Requires g and gives an iterator of match objects.
Need to rewrite textreplace / replaceAllUse replacement patterns or a function replacer.

The trap is not that g is bad. It is that a single regex object can carry state between calls. Reset lastIndex, create a fresh regex, or use a string method that manages the iteration for you.

Match objects and indices

exec() returns null when nothing matches. When it succeeds, it returns an array-like match object. match[0] is the full match, later entries are captured groups, index is the start position, and input is the original string.

Reading a match objectPop out in the code editor (opens in a new tab)JavaScript
const pattern = /(?<tag>#[A-Za-z]+)/d;const text = "Use #JS today";const match = pattern.exec(text); console.log(match[0]);console.log(match.index);console.log(match.input === text);console.log(match.groups.tag);console.log(match.indices[0].join("-"));console.log(match.indices.groups.tag.join("-"));

The named group and d flag are previews. Groups get their own lesson; this lesson only needs you to know that groups can name captured text and indices can show where the full match and captures live in the input.

String methods that accept regexes

SORT IT

Regexes become practical through string methods. search returns an index. match returns simple matches or one detailed match. matchAll gives every detailed match. replace, replaceAll, and split transform text.

Search, match, matchAll, split, replace, replaceAllPop out in the code editor (opens in a new tab)JavaScript
const text = "Order 2026-09-26: chai, cake. Tags: #JS #web"; console.log(text.search(/chai/i));console.log(text.match(/#[A-Za-z]+/g).join(", "));console.log([...text.matchAll(/#[A-Za-z]+/g)].map((m) => `${m[0]}@${m.index}`).join(" | "));console.log("red, green; blue".split(/,\s*|;\s*/).join("|"));console.log(text.replace(/(\d{4})-(\d{2})-(\d{2})/, "$3/$2/$1"));console.log("cat cat".replaceAll(/cat/g, "dog"));

Replacement patterns

Replacement strings have their own mini-language. $& means the whole match, $1 means the first captured group, $<name> means a named group, and a function replacer can compute the replacement in JavaScript.

Replacement strings and a function replacerPop out in the code editor (opens in a new tab)JavaScript
console.log("cat".replace(/cat/, "[$&]"));console.log("Ada Lovelace".replace(/([A-Za-z]+) ([A-Za-z]+)/, "$2, $1"));console.log("#javascript".replace(/#(?<name>[a-z]+)/, "topic:$<name>"));console.log("fee fi".replace(/f[a-z]+/g, (match) => match.toUpperCase()));
Choose the regex API
  • Does this form field look like an email address?
  • Find the first hashtag and where it starts.
  • List every hashtag with its index.
  • Turn `2026-09-26` into `26/09/2026`.
  • Wrap every search result in square brackets.
  • Return just `["#JS", "#web"]` from a short note.
Try it yourself
0 of 6 correct

Sort each task by the kind of result you need. The same pattern can be useful with different APIs.

Choose a category for every card. You can change an answer at any time; Reset clears them all.

Try patterns in a safe tester

PLAYGROUND

A tester helps you connect the pattern, flags, text, and match result. This one builds a RegExp inside try/catch, caps input length, refuses obvious slow nested quantifiers, and renders highlights as React text instead of HTML.

Live regex tester
How the tester collects matchesPop out in the code editor (opens in a new tab)JavaScript
const pattern = new RegExp("#[A-Za-z]+", "gi");const text = "Learning #JavaScript and #regex";const matches = [...text.matchAll(pattern)].map((match) => ({  text: match[0],  index: match.index,})); console.log(matches.map((match) => `${match.text}@${match.index}`).join(", "));
Matches2 found
Learning #JavaScript and #regex with JS.
  1. #JavaScript 9..20
  2. #regex 25..31
Try it yourself

2 matches. Indexes count from zero; end positions stop just after the match.

Inputs are length-capped and compiled inside try/catch. The tester refuses obvious nested-quantifier patterns; the performance lesson covers robust ReDoS defenses.

Try #[A-Za-z]+ with gi, then try an invalid pattern such as (. If you add d, the match list also shows index spans from the regex engine.

Practical uses

Regex basics show up in everyday UI work: quick form feedback, finding hashtags or codes, reformatting date strings with known shapes, and highlighting search terms. Keep validation honest: client-side regex is helpful feedback, not a trusted security boundary.

Four practical regex tasksPop out in the code editor (opens in a new tab)JavaScript
const email = "ada@example.com";const text = "Learning #JavaScript and #regex on 2026-09-26";const term = "js"; console.log(/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email));console.log(text.match(/#[A-Za-z]+/g).join(", "));console.log(text.replace(/(\d{4})-(\d{2})-(\d{2})/, "$3/$2/$1"));console.log("JS regex basics".replace(new RegExp(term, "gi"), "[$&]"));
Good regex boundaries

Regex is excellent for regular text shapes. Reach for a parser when the input is nested or language-like, such as full HTML, JavaScript, JSON with comments, or complex URLs. The performance lesson later covers catastrophic backtracking and ReDoS.

Common misconceptions

  • “A regex understands meaning.” It only follows the pattern. It can find email-shaped text; it cannot prove the mailbox exists.
  • “g only means find all.” It also makes test() and exec() advance lastIndex on the regex object.
  • “match and matchAll are interchangeable.” match() changes shape with g; matchAll() gives detailed objects for every match and requires g.
  • “The constructor uses the same escaping as a literal.” Constructor patterns are strings first, so backslashes often need another backslash.
  • “Regex is always the shortest correct solution.” Sometimes startsWith, includes, URL, Intl, or a parser is clearer and safer.
Similar-looking methods, different return shapes
MethodReturnsBest use
test()BooleanQuick yes/no checks.
exec()One match object or nullRead index, groups, and indices for the next match.
match()Strings with g; one match object without gConvenient simple matching.
matchAll()Iterator of match objectsLoop through every detailed match.

Practice exercises

5 EXERCISES
Exercise 1 · Warm-upCase-insensitive test

Predict the boolean printed by the snippet.

Starter codePop out in the code editor (opens in a new tab)JavaScript
const answer = /complete/i.test("CompleteFrontend");
console.log(answer);

Answer, then press Check. Spacing and letter case don’t matter.

    Exercise 2 · PracticeTrace the lastIndex trap

    Type all six printed values, separated by commas.

    Starter codePop out in the code editor (opens in a new tab)JavaScript
    const word = /js/g;
    const text = "js js";
    console.log(word.test(text));
    console.log(word.lastIndex);
    console.log(word.test(text));
    console.log(word.lastIndex);
    console.log(word.test(text));
    console.log(word.lastIndex);

    Answer, then press Check. Spacing and letter case don’t matter.

      Exercise 3 · PracticeList every hashtag with an index

      Predict the exact joined output.

      Starter codePop out in the code editor (opens in a new tab)JavaScript
      const text = "Ship #JS and #regex";
      console.log([...text.matchAll(/#[A-Za-z]+/g)].map((match) => match[0] + "@" + match.index).join(" | "));

      Answer, then press Check. Spacing and letter case don’t matter.

        Exercise 4 · PracticeReformat a date

        Type the reformatted date printed by the code.

        Starter codePop out in the code editor (opens in a new tab)JavaScript
        const input = "2026-09-26";
        console.log(input.replace(/(\d{4})-(\d{2})-(\d{2})/, "$3/$2/$1"));

        Answer, then press Check. Spacing and letter case don’t matter.

          Exercise 5 · ChallengeEscape a search term before highlighting

          Predict the transformed text.

          Starter codePop out in the code editor (opens in a new tab)JavaScript
          const userText = "a.b";
          const escaped = userText.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
          const pattern = new RegExp(escaped, "g");
          console.log("a.b axb".replace(pattern, "[$&]"));

          Answer, then press Check. Spacing and letter case don’t matter.

            Check your understanding

            8 QUESTIONS
            Lesson quiz · 8 questionsScore: first tries count
            1. Question 1 of 8Which statement best defines a regular expression?

              Choose an answer to see the explanation.

            2. Question 2 of 8What does the case-insensitive test print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const pattern = /cat/i;
              console.log(pattern.test("CAT"));

              Choose an answer to see the explanation.

            3. Question 3 of 8Which constructor pattern safely looks for a digit?

              Choose an answer to see the explanation.

            4. Question 4 of 8What is the g-flag trap in this code?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const word = /js/g;
              console.log(word.test("js js"));
              console.log(word.test("js js"));
              console.log(word.test("js js"));

              Choose an answer to see the explanation.

            5. Question 5 of 8What does the d flag add to a match object?

              Choose an answer to see the explanation.

            6. Question 6 of 8What do the hashtag matches print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const text = "Tags: #JS #web";
              console.log([...text.matchAll(/#[A-Za-z]+/g)].map((m) => m[0]).join(","));

              Choose an answer to see the explanation.

            7. Question 7 of 8Which replacement pattern means the whole match?

              Choose an answer to see the explanation.

            8. Question 8 of 8What does the date replacement print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              console.log("2026-09-26".replace(/(\d{4})-(\d{2})-(\d{2})/, "$3/$2/$1"));

              Choose an answer to see the explanation.

            Key takeaways

            • A regex is a RegExp pattern object used with strings.
            • Use literals for fixed patterns and new RegExp() for variable patterns.
            • Flags change behavior; g and y also make lastIndex matter.
            • exec() and matchAll() expose match objects; d adds index spans.
            • Choose the string method that matches the result you need: find, list, split, or replace.

            Remember the one-liner.
            A regex is a compact text pattern plus flags; use it when a pattern is clearer than hand-written string checks.

            Up next: Character classes & sets.

            CompleteFrontend Clear concepts. Working examples.