A JavaScript regular expression (RegExp) defines a search pattern for matching, validating, or replacing text. You create one with slash literals like /pattern/flags or dynamically via new RegExp(pattern, flags).
Combine flags after the closing slash to control how the engine matches text:
g (global): Finds every match across the string instead of stopping at the first one.i (case-insensitive): Treats uppercase and lowercase letters identically.m (multiline): Makes ^ and $ match the start and end of every line.u (unicode): Enables proper matching for emojis and Unicode properties.Use regex.test(str) for fast boolean checks, str.matchAll(regex) to loop through matches and capture groups, and str.replace(regex, fn) for transformations.
Named capture groups (?<name>...) make extracted fields easy to read without remembering group index numbers.
const slugPattern = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
console.log("Valid slug:", slugPattern.test("js-async-await")); // true
console.log("Bad slug: ", slugPattern.test("JS_Async!")); // false
const logLine = "2026-11-12 [ERROR] code=503 service=auth";
const logRegex = /(?<date>\d{4}-\d{2}-\d{2})\s+\[(?<level>\w+)\]\s+code=(?<code>\d+)/;
const match = logLine.match(logRegex);
if (match?.groups) {
console.log("Parsed log:", match.groups);
}
/g flag with regex.test() in a loop: A global regex stores stateful .lastIndex between .test() calls, causing every second call on the same string to return false! Drop /g when calling .test().new RegExp(input): Characters like ., *, or [ inside user input break regex syntax or match everything. Use RegExp.escape() where supported or escape special regex tokens first.(a+)+: Backtracking explosions can freeze the browser tab on long non-matching strings (ReDoS). Keep quantifiers simple and non-overlapping.new RegExp() instead of /.../ literal syntax?Use /.../ literals for fixed patterns known at write time because the syntax is cleaner and avoids double-escaping backslashes. Use new RegExp() only when building a pattern from a dynamic variable.
matchAll() safer than exec() in a while loop?str.matchAll(regex) returns a clean iterator of all matches without requiring manual .lastIndex tracking.
Use a practical check like /^[^\s@]+@[^\s@]+\.[^\s@]+$/ for basic client feedback, and verify delivery on the backend.
Sign in to track your learning journey, earn industry-recognized certificates, and join our elite developer community.
Quick Access With
Experiment with the code from this lesson in our interactive playground.