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
| Flag | Property | Name | Effect |
|---|---|---|---|
g | global | Global | Find all matches rather than stopping at the first. |
i | ignoreCase | Ignore case | Match without regard to upper/lower case. |
m | multiline | Multiline | Make ^ and $ match at line breaks, not just string start/end. |
s | dotAll | Dot-all | Let . match newline characters too. |
u | unicode | Unicode | Treat the pattern as a sequence of Unicode code points. |
y | sticky | Sticky | Match only at the exact position given by lastIndex. |
d | hasIndices | Indices | Add 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 totest()orexec()can give surprising results — resetlastIndexto0or 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 theuflag is present. Using them withoututhrows aSyntaxError.
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
gwhenever you expect more than one match, orreplaceAll/matchAllwill throw or under-match. - Default to the
uflag for any pattern that may touch emoji, accented text, or non-Latin scripts. - Avoid reusing a single
g/yregex instance across calls unless you deliberately managelastIndex. - Prefer
iover hand-written character classes like[Aa]for readable case-insensitivity. - Reach for
monly when you genuinely work line-by-line; otherwise^and$should anchor the whole string. - Use
sinstead of workarounds like[\s\S]when you simply want.to span newlines. - Use the sticky
yflag for performance-sensitive tokenizers where anchored, position-based matching matters.