Unicode
Without the u flag, regex character classes, ., and quantifiers treat strings as UTF-16 code units. With u (or v in modern engines), they work on Unicode code points and unlock property escapes.
u / v flags + property escapes
EXAMPLE
// 1) Without /u — char classes lie about non-BMP code points
/^.{1}$/.test('🇦🇺') // FALSE — surrogate pair is 2 code units
/^.{1}$/u.test('🇦🇺') // also FALSE — 2 code POINTS (regional indicators)
/^.$/v.test('🇦🇺') // TRUE — with /v if you intended grapheme behaviour
// 2) Property escapes — \p{Property}
/\p{Letter}+/u.test('café') // true
/\p{Lowercase}+/u.test('hello')
/\p{Decimal_Number}+/u.test('۴۲') // Arabic-Indic digits
/\p{Emoji}+/u.test('hi 🎉') // true
// Script
/\p{Script=Greek}+/u.test('αβγ')
/\p{Script=Cyrillic}+/u.test('Привет')
/\p{Script=Han}+/u.test('日本語')
// General category abbreviations
/\p{L}+/u // any letter
/\p{N}+/u // any number
/\p{P}+/u // any punctuation
/\p{Sc}+/u // currency symbol
// Negate with \P
/\P{Letter}+/u.test('123') // true
// 3) The /v flag (modern) — set difference + intersection
/[\p{Letter}--[a-z]]/v.test('A') // letters minus lowercase ASCII
/[\p{Letter}&&\p{ASCII}]/v.test('a') // letters AND ASCII
// 4) Length the way users expect — graphemes
const s = '🇦🇺café';
s.length // 6 — UTF-16 code units
[...s].length // 5 — code points
new Intl.Segmenter('en', { granularity: 'grapheme' }).segment(s).length || (() => {
let n = 0;
for (const _ of new Intl.Segmenter('en', { granularity: 'grapheme' }).segment(s)) n++;
return n;
})() // 4 — what a user would count
// 5) Normalisation — different ways to spell the SAME character
'é' === 'é' // false — one is precomposed, one is e + combining acute
'é'.normalize('NFC') === 'é'.normalize('NFC') // true
// Always normalise before comparison / regex on text from unknown sources.
// 6) Case-insensitive Unicode
/STRA\u00DFE/iu.test('straße') // true (ß ↔ SS folding works with /iu)
Why it matters
Add the u flag to every regex that may see non-ASCII text. Without it, even simple length checks lie about emoji, CJK, and any combining-mark text — one of the most-shipped silent bugs.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
// /u flag enables proper code-point matching + property escapes.
const letters = /\p{L}+/gu; // any Unicode letter
'Café — déjà vu'.match(letters); // ['Café','déjà','vu']
Try it Yourself »
Discussion
Loading…