Third bug report this year from a form that "limits names to 20 characters".
'é'.length is 2 in JS (e + combining accent), while 'é' typed as one code point is 1. They look identical. Most emoji are 2, because length counts UTF-16 units. The family emoji with zero-width joiners is 11.
What to use depends on why you're counting:
- bytes for a storage limit: Buffer.byteLength or TextEncoder
- what a person calls a character: Intl.Segmenter with granularity 'grapheme'
- comparing strings: normalize('NFC') both sides first
[...s].length gets you code points, which is the one people reach for, and it's still not what a person would count.