La flag unicode /.../u abilita il corretto supporto delle coppie surrogate.
Qui vi sono i valori unicode da comparare:
| Carattere | Unicode | Bytes |
|---|---|---|
a |
0x0061 | 2 |
â |
0x2248 | 2 |
ð³ |
0x1d4b3 | 4 |
ð´ |
0x1d4b4 | 4 |
ð |
0x1f604 | 4 |
Dunque caratteri come a e â occupano 2 bytes, e quelli rari ne occupano 4.
Unicode è stato fatto in modo tale che i caratteri a 4 byte abbiano un significato solo considerando lâintero insieme.
In precedenza JavaScript non ne sapeva nulla, e molti metodi delle stringhe ancora presentano problemi. Per esempio, length pensa che qui ci siano due caratteri:
alert('ð'.length); // 2
alert('ð³'.length); // 2
â¦Ma possiamo vedere che ce nâè solo uno, giusto? Il punto è che length tratta i caratteri a 4 byte come due caratteri a 2-byte. Questo non è corretto, perché devono essere considerati solo insieme (per cui chiamati âcoppie surrogateâ).
Usualmente, anche le espressioni regolari trattano questi âcaratteri lunghiâ come due caratteri a 2-byte.
Questo porta a strani risultati, ad esempio proviamo a cercare [ð³ð´] nella stringa ð³:
alert( 'ð³'.match(/[ð³ð´]/) ); // risultato strano (in realtà è una corrispondenza errata, "mezzo carattere")
Il risultato è errato, perché di default il motore delle regexp non comprende le coppie surrogate.
Dunque, pensa che [ð³ð´] non siano due, ma quattro caratteri:
- la metà sinistra di
ð³(1), - la metà destra di
ð³(2), - la metà sinistra di
ð´(3), - la metà destra di
ð´(4).
Li possiamo elencare così:
for(let i=0; i<'ð³ð´'.length; i++) {
alert('ð³ð´'.charCodeAt(i)); // 55349, 56499, 55349, 56500
};
Quindi trova solo la âmetà sinistraâ di ð³.
In altre parole, la ricerca funziona come '12'.match(/[1234]/): solo 1 viene restituito.
La flag âuâ
La flag /.../u risolve questo problema.
Essa abilita le coppie surrogate nel motore delle regexp, in modo tale che il risultato sia:
alert( 'ð³'.match(/[ð³ð´]/u) ); // ð³
Vediamo un altro esempio.
Se dimentichiamo la flag u e occasionalmente usiamo le coppie surrogate, possiamo incorrere in errori:
'ð³'.match(/[ð³-ð´]/); // SyntaxError: intervallo non valido nella classe di caratteri
Di solito, le regexp interpretano [a-z] come un "intervallo di caratteri con codici tra a e z.
Ma senza la flag u, le coppie surrogate vengono interpretate come âcoppie di caratteri indipendentiâ, quindi [ð³-ð´] è come [<55349><56499>-<55349><56500>] (sostituito a ogni coppia surrogata il codice corrispondente). Ora possiamo vedere con più chiarezza che lâintervallo 56499-55349 non è accettabile, dato che il valore a sinistra dellâintervallo deve essere inferiore rispetto a quello a destra.
Usando la flag u tutto funziona di nuovo:
alert( 'ð´'.match(/[ð³-ðµ]/u) ); // ð´
Commenti
<code>, per molte righe â includile nel tag<pre>, per più di 10 righe â utilizza una sandbox (plnkr, jsbin, codepenâ¦)