Después de muchos intentos de comprensión, debo decir que no entiendo cómo funciona String.prototype.normalize() . Hay algunos valores que este método puede tomar como parámetros: NFC , NFD , NFKC , NFKD .
En primer lugar, no entiendo cuál es la diferencia entre NFD y NFKD . La especificación es muy vaga al respecto, así que... En algún recurso he leído que NFD descompone los caracteres por equivalencia canónica. Por ejemplo:
"â" (U+00E2) -> "a" (U+0061) + " ̂" (U+0302) Y NFKD descompone los caracteres por compatibilidad. Por ejemplo:
"fi" (U+FB01) -> "f" (U+0066) + "i" (U+0069) Pero eso no es exactamente cierto. NFKD no solo descompone los caracteres por compatibilidad. También puede tratar perfectamente con el primer ejemplo:
let s = `\u00E2`; //"â" console.log(s.normalize('NFD').length); //2 console.log(s.normalize('NFKD').length); //2 ¿Significa que NFKD puede descomponer caracteres por compatibilidad y también por equivalencia canónica? ¿Y NFD descompone los caracteres solo por equivalencia canónica...?
let s = `\uFB01`; //"fi" console.log(s.normalize('NFD').length); //1El tipo de descomposición completa elegido depende de la forma de normalización Unicode involucrada. Para NFC o NFD, uno hace una descomposición canónica completa, que utiliza solo valores canónicos de Decomposition_Mapping. Para NFKC o NFKD, se realiza una descomposición de compatibilidad completa, que utiliza valores de Decomposition_Mapping canónicos y de compatibilidad.
Es por eso que NFC/NFD y NFKC/NFKD funcionan así:
let s1 = '\uFB00'; //"ff" let s2 = '\u0066\u0066'; //"ff" console.log(s1.normalize('NFD').length); //doesn't work with compatible -- only can. eq. let t1 = `\u00F4`; //ô let t2 = `\u006F\u0302`; //ô console.log(t1.normalize('NFKD').length); //also works with can. eq. console.log(t2.normalize('NFKC').length); //also works with can. eq.Y eso es totalmente comprensible porque...
Todas las secuencias canónicamente equivalentes también son compatibles, pero no al revés.