Risposta tecnica diretta
Le stringhe JavaScript sono sequenze di unità di codice UTF-16 a 16 bit, non caratteri Unicode individuali o simboli percepiti dall'utente. I caratteri supplementari al di fuori del Basic Multilingual Plane (come le emoji e gli ideogrammi rari) richiedono due unità di codice UTF-16 (una coppia surrogata), mentre i grafemi composti richiedono più punti di codice.
La differenza tra unità di codice UTF-16, punti di codice Unicode e cluster di grafemi in JavaScript
const emoji = '😀';
// 1. String.prototype.length counts UTF-16 code units
console.log(emoji.length); // 2
// 2. String iterator ([...str]) counts Unicode code points
console.log([...emoji].length); // 1
// 3. Composite emoji with Zero-Width Joiner (ZWJ)
const family = '👨👦';
console.log(family.length); // 5 code units
console.log([...family].length); // 3 code points
// 4. Intl.Segmenter counts user-perceived grapheme clusters
const segmenter = new Intl.Segmenter('en', { granularity: 'grapheme' });
console.log([...segmenter.segment(family)].length); // 1 user character
2
1
5
3
1
Perché accade: il modello di stringhe di ECMAScript
Per comprendere il comportamento delle stringhe JavaScript, gli sviluppatori devono capire i tre livelli distinti di rappresentazione Unicode nel browser e in Node.js.
1. L'eredità storica di UTF-16
2. Unità di codice vs punti di codice
3. Punti di codice vs cluster di grafemi percepiti dall'utente
4. Surrogati isolati e stringhe mal formate
Modello di esecuzione di linguaggio e runtime
V8 usa un'ottimizzazione della rappresentazione interna: le stringhe che contengono solo caratteri Latin-1 (U+0000..U+00FF) sono memorizzate come array a 1 byte (SeqOneByteString). Le stringhe che contengono un carattere al di sopra di U+00FF sono promosse ad array UTF-16 a 2 byte (SeqTwoByteString).
Errori comuni vs modelli di produzione
Scopri quali modelli falliscono in produzione e le alternative moderne conformi agli standard.
Contare i caratteri visibili all'utente
Contatore di caratteri in form di interfaccia, limiti SMS, campi biografia.const str = '👨💻';
console.log(str.length);
// Returns 5 (UTF-16 code units)
const str = '👨💻';
const segmenter = new Intl.Segmenter('en', { granularity: 'grapheme' });
console.log([...segmenter.segment(str)].length);
// Returns 1 (true user-perceived character)
Iterare i caratteri di una stringa
Analisi di token, costruzione di trasformatori di stringhe personalizzati.const text = '🔥hello';
for (let i = 0; i < text.length; i++) {
console.log(text[i]); // splits 🔥 into \uD83D and \uDD25!
}
const chars = text.split(''); // ['\uD83D', '\uDD25', 'h', 'e', 'l', 'l', 'o']
const text = '🔥hello';
for (const char of text) {
console.log(char); // '🔥', 'h', 'e', 'l', 'l', 'o'
}
const chars = [...text]; // ['🔥', 'h', 'e', 'l', 'l', 'o']
Leggere punti di codice numerici
Convertitori di codifica dei caratteri, hash crittografico, metriche dei font.const char = '😀';
console.log(char.charCodeAt(0).toString(16));
// Returns 'd83d' (High surrogate only!)
const char = '😀';
console.log(char.codePointAt(0).toString(16));
// Returns '1f600' (True Unicode code point!)
Scrivere sequenze di escape Unicode
Letterali di codice sorgente, payload JSON, definizioni di espressioni regolari.const fire = '\uD83D\uDD25'; // 🔥
// Prone to transposition, hard to read, manual math needed
const fire = '\u{1F525}'; // 🔥
const smile = '\u{1F600}'; // 😀
Matrice dei casi limite e invarianti
Una matrice di test diversificata che confronta il comportamento dei caratteri tra ASCII, segni combinanti, emoji, bandiere e frammenti surrogati.
| Caso di test | Glifo di input | Unità di codice | Punti di codice | Grafemi | Categoria | Spiegazione tecnica |
|---|---|---|---|---|---|---|
| Lettera latina ASCII | A |
1
|
1
|
1
|
Basic Latin | U+0041 sta in un singolo byte a 7 bit, un'unità di codice a 16 bit e un punto di codice. |
| Accento precomposto | é |
1
|
1
|
1
|
Latin-1 Supplement | U+00E9 accento acuto precomposto nel BMP. 1 unità di codice, 1 punto di codice, 1 grafema. |
| Accento scomposto | é |
2
|
2
|
1
|
Combining Mark | Lettera base e (U+0065) + accento acuto combinante (U+0301). 2 punti di codice resi come 1 grafema visivo. |
| Simbolo di valuta | € |
1
|
1
|
1
|
Currency | Segno dell'euro U+20AC situato nel BMP. 1 unità di codice, 1 punto di codice, 1 grafema. |
| Emoji standard | 😀 |
2
|
1
|
1
|
Supplementary Plane | Faccina sorridente U+1F600 nel piano 1. Codificata come 2 unità di codice UTF-16 (D83D DE00). |
| Sequenza di emoji con ZWJ | 👨👦 |
5
|
3
|
1
|
Emoji Sequence | Uomo (U+1F468) + ZWJ (U+200D) + ragazzo (U+1F466). 3 punti di codice uniti in 1 glifo di famiglia. |
| Bandiera dell'arcobaleno | 🏳️🌈 |
6
|
4
|
1
|
Emoji Sequence | Bandiera bianca (U+1F3F3) + selettore di variazione 16 (U+FE0F) + ZWJ (U+200D) + arcobaleno (U+1F308). |
| Bandiera nazionale (indicatori regionali) | 🇺🇳 |
4
|
2
|
1
|
Flag Sequence | Indicatore regionale U (U+1F1FA) + indicatore regionale N (U+1F1F3). 2 punti di codice, 1 grafema. |
| Surrogato alto isolato |
1
|
1
|
1
|
Surrogate Fragment | Surrogato alto isolato 0xD83D. Valido nella memoria di ECMAScript, ma mal formato in UTF-8. |
Core API Reference
Standard library methods, runtime signatures, and Unicode semantics.
str.codePointAt(index: number): number | undefined
Restituisce il valore del punto di codice Unicode (intero) all'indice di unità di codice UTF-16 specificato.
String.fromCodePoint(...codePoints: number[]): string
Crea una stringa a partire da una sequenza di punti di codice Unicode a 21 bit.
new Intl.Segmenter(locales?: string | string[], options?: { granularity: "grapheme" | "word" | "sentence" })
Fornisce la segmentazione del testo sensibile alla locale, consentendo un'iterazione affidabile dei cluster di grafemi percepiti dall'utente.
str.normalize(form?: "NFC" | "NFD" | "NFKC" | "NFKD"): string
Restituisce la forma di normalizzazione Unicode della stringa chiamante.
new RegExp(pattern, "v")
Flag UnicodeSets per le espressioni regolari di ECMAScript 2024, che abilita operazioni di insieme e proprietà di stringa.
Ispettore interattivo di stringhe e Unicode in JavaScript
Provare qualsiasi stringa o sequenza di emoji in tempo reale per ispezionarne le unità di codice UTF-16, i punti di codice Unicode e i cluster di grafemi nel browser.
Scomposizione del punto di codice:
Standard e provenienza delle fonti
Tutti gli invarianti tecnici, le API e i comportamenti di questa guida sono verificati rispetto alle specifiche primarie ufficiali.
ECMAScript 2024 Language Specification (ECMA-262 15th Edition)
Clausola: §6.1.4 The String Type & §22.1 String Objects
ECMAScript Internationalization API (ECMA-402)
Clausola: §18 Intl.Segmenter Objects
Unicode Standard Annex #29: Unicode Text Segmentation
Clausola: §3 Grapheme Cluster Boundaries
Unicode Standard Annex #15: Unicode Normalization Forms
Clausola: §1 Normalization Forms
JavaScript String Reference & UTF-16 Representation
Clausola: UTF-16 Characters, Unicode Code Points, and Grapheme Clusters