iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

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…