Skip to content
JavaScript js regex 4 min read

Flags

Flags are single-letter modifiers attached to a regular expression that change how the pattern is matched. They control whether matching is case-sensitive, whether the engine finds every match or just the first, how anchors like ^ and $ behave, and which Unicode rules apply. Choosing the right flags is often the difference between a regex that “almost works” and one that does exactly what you intend.

Where flags go

In a regex literal, flags come after the closing slash. With the RegExp constructor, they are passed as a second string argument. You can combine multiple flags in any order.

const literal = /hello/gi;
const built = new RegExp("hello", "gi");

console.log(literal.flags); // "gi"
console.log(built.global, built.ignoreCase); // true true

Output:

gi
true true

Each flag is also exposed as a read-only boolean property on the regex instance (global, ignoreCase, multiline, dotAll, unicode, sticky), and the full string is available on .flags.

The flags at a glance

FlagPropertyNameEffect
gglobalGlobalFind all matches rather than stopping at the first.
iignoreCaseIgnore caseMatch without regard to upper/lower case.
mmultilineMultilineMake ^ and $ match at line breaks, not just string start/end.
sdotAllDot-allLet . match newline characters too.
uunicodeUnicodeTreat the pattern as a sequence of Unicode code points.
ystickyStickyMatch only at the exact position given by lastIndex.
dhasIndicesIndicesAdd start/end index data to match results.

g — global

Without g, methods like String.prototype.match and String.prototype.replace act on only the first match. With g, they operate across the whole string.

const text = "cat dog cat dog";

console.log(text.match(/cat/));   // first match only
console.log(text.match(/cat/g));  // every match
console.log(text.replace(/cat/g, "fish"));

Output:

[ 'cat', index: 0, input: 'cat dog cat dog', groups: undefined ]
[ 'cat', 'cat' ]
fish dog fish dog

Tip: A global or sticky regex stored in a variable keeps internal state in lastIndex. Reusing it across calls to test() or exec() can give surprising results — reset lastIndex to 0 or create a fresh regex each time.

i — ignore case

The i flag makes letter matching case-insensitive, so a single pattern matches every casing variant.

console.log(/javascript/i.test("JavaScript")); // true
console.log("HELLO".replace(/hello/i, "hi"));  // "hi"

Output:

true
hi

m — multiline

By default ^ matches only the start of the whole string and $ only the end. With m, they also match at the beginning and end of each line (around \n).

const lines = "first\nsecond\nthird";

console.log(lines.match(/^\w+/g));   // without m
console.log(lines.match(/^\w+/gm));  // with m

Output:

[ 'first' ]
[ 'first', 'second', 'third' ]

s — dotAll

The dot . normally matches any character except line terminators. The s flag makes . match newlines too, which is handy for matching across lines.

const html = "<p>line one\nline two</p>";

console.log(/<p>(.*)<\/p>/.test(html));  // false, dot stops at \n
console.log(/<p>(.*)<\/p>/s.test(html)); // true

Output:

false
true

u — unicode

The u flag enables full Unicode mode. It makes \u{...} code-point escapes, Unicode property escapes (\p{...}), and surrogate-pair handling work correctly. Without it, characters outside the Basic Multilingual Plane are treated as two separate units.

console.log("😀".match(/./u)[0].length); // 2 (one code point)
console.log(/\p{Emoji}/u.test("😀"));     // true
console.log(/\u{1F600}/u.test("😀"));      // true

Output:

2
true
true

Warning: \p{...} property escapes and \u{...} code-point escapes are only valid when the u flag is present. Using them without u throws a SyntaxError.

y — sticky

A sticky regex matches only starting exactly at the index stored in lastIndex. It does not scan forward looking for a match, which makes it ideal for tokenizers and parsers.

const re = /\d+/y;
re.lastIndex = 4;

console.log(re.exec("abc 123 def")); // null — position 4 is a space
re.lastIndex = 4;
console.log(re.exec("abc 1234567")); // matches at exactly index 4

Output:

null
[ '1234567', index: 4, input: 'abc 1234567', groups: undefined ]

Combining flags

Flags stack freely. A common pairing is gi for a global, case-insensitive search-and-replace.

const post = "JavaScript and javascript and JAVASCRIPT";
const highlighted = post.replace(/javascript/gi, "JS");

console.log(highlighted);

Output:

JS and JS and JS

Best practices

  • Add g whenever you expect more than one match, or replaceAll / matchAll will throw or under-match.
  • Default to the u flag for any pattern that may touch emoji, accented text, or non-Latin scripts.
  • Avoid reusing a single g/y regex instance across calls unless you deliberately manage lastIndex.
  • Prefer i over hand-written character classes like [Aa] for readable case-insensitivity.
  • Reach for m only when you genuinely work line-by-line; otherwise ^ and $ should anchor the whole string.
  • Use s instead of workarounds like [\s\S] when you simply want . to span newlines.
  • Use the sticky y flag for performance-sensitive tokenizers where anchored, position-based matching matters.
Last updated June 1, 2026
Was this helpful?