ByteTips.

Guide

How to Use Regex in JavaScript

Regex looks like keyboard noise, but twenty percent of it covers ninety percent of real tasks. Learn literals, methods, flags, and the three traps everyone hits.

October 14, 2026 · 4 min read · Shayan

Regular expressions have a reputation problem. They look like someone fell asleep on the keyboard, and every developer has a story about a regex that worked until it suddenly did not. But regex is simply a tiny language for describing patterns in text: find all the emails, validate this phone number, pull the IDs out of this log file. You already use it every time you search with a wildcard. Learning the twenty percent of regex you actually use covers ninety percent of real tasks, and this post is that twenty percent.

What a regex actually is

A regex is a pattern, not a string. Instead of saying 'find the text abc', you say 'find a digit, followed by two letters, followed by an optional hyphen'. The engine walks through the text and reports every match. JavaScript has regex built in: /pattern/flags is a literal, and new RegExp('pattern', 'flags') builds one from a string. The pattern is made of literal characters (a, 5, @) and metacharacters with special meaning: . matches any character, \d matches a digit, \w matches a word character, \s matches whitespace, ^ anchors to the start, $ anchors to the end.

The two ways to write one

Use a literal when the pattern is fixed, and the constructor when it is built from variables — like a search box input. The constructor needs double-escaped backslashes, which is the most common source of confusion:

const literal = /\d{3}-\d{4}/; // matches 555-1234
const fromString = new RegExp("\\d{3}-\\d{4}"); // same pattern

literal.test("Call 555-1234"); // true

Prefer literals unless the pattern is dynamic. They are easier to read and you skip the escaping headache.

The methods you will use every day

Five methods cover nearly all regex work:

const text = "Order 42 ships on 2026-01-05.";

/\d+/.test(text); // true — is there a number?
text.match(/\d+/g); // ["42", "2026", "01", "05"]
text.matchAll(/\d+/g); // iterator with positions
text.replace(/\d+/, "#"); // "Order # ships on 2026-01-05."
text.split(/\s+/); // ["Order", "42", "ships", "on", "2026-01-05."]

Note the difference between match and matchAll: match with the g flag returns only the matched strings, while matchAll returns match objects with capture groups and positions — what you want when you need to extract structured data.

Flags that change everything

Flags after the closing slash change how the pattern behaves:

  • g — global: find all matches, not just the first.
  • i — case-insensitive: /abc/i matches ABC, Abc, aBc.
  • m — multiline: ^ and $ match line starts and ends, not just the whole string.
  • s — dotAll: . also matches newlines, which it does not by default.
  • u — unicode: correct handling of emoji and astral characters.

The mistakes everyone makes

Three traps catch nearly everyone. First, greedy quantifiers: .* matches as much as possible, so /<.*>/ on '<b>hi</b>' matches the whole string, not just '<b>'. Add ? to make it lazy: /<.*?>/ stops at the first closing bracket. Second, forgetting to escape: a dot in a domain pattern must be \., or 'example.com' matches 'exampleXcom'. Third, catastrophic backtracking: nested quantifiers like (a+)+ on long non-matching input can hang your program. If a regex feels slow, it is usually nested quantifiers, and the fix is to simplify the pattern or cap the input length.

Try it

Test any pattern with live matches, flags, and match counts in the Regex Tester — paste your pattern and your text and see matches instantly. The same site has a Case Converter for renaming the identifiers your patterns extract. And if the text you are matching is JSON, How to Format JSON in JavaScript shows how to pretty-print it first so patterns are easier to see.

More guides