Flags go after the closing slash and change how the whole pattern behaves.
/pattern/gi
| Flag | Name | Effect |
|---|---|---|
g | global | find all matches, not just the first |
i | ignore case | a matches A |
m | multiline | ^ and $ match at each line |
s | dotAll | . also matches line breaks |
u | unicode | proper handling of Unicode characters |
y | sticky | match only at the exact lastIndex |
d | indices | include start/end positions of matches |
g: all matches
const text = "cat, Cat, cAt";
console.log(text.match(/cat/)); // first match only (with details)
console.log(text.match(/cat/g)); // → ["cat"]
console.log(text.match(/cat/gi)); // → ["cat", "Cat", "cAt"]
i: ignore case
console.log(/hello/i.test("HELLO")); // → true
console.log(/hello/.test("HELLO")); // → false
m: multiline
const lines = "one\ntwo\nthree";
console.log(lines.match(/^\w+$/g)); // → null (^ and $ only match the whole text)
console.log(lines.match(/^\w+$/gm)); // → ["one", "two", "three"]
u: unicode
Without u, an emoji counts as two characters in a pattern. Use u when you work with non-English text or emoji.
console.log("😀".length); // → 2
console.log(/^.$/.test("😀")); // → false
console.log(/^.$/u.test("😀")); // → true
The lastIndex gotcha with g
A regex that has the g (or y) flag remembers where it stopped, in its lastIndex property. Calling test() repeatedly on the same regex can give surprising results.
const re = /a/g;
console.log(re.test("a")); // → true
console.log(re.test("a")); // → false (it continued after the first match!)
If you use test() for validation, do not use the g flag. Or create the regex fresh each time.
Combining flags
The order does not matter: /x/gi and /x/ig are the same.
const re = new RegExp("hello", "gi");
console.log(re.flags); // → gi