1. ¿Qué es Unicode?
Unicode se originó a partir de una idea muy simple: incluir todos los personajes del mundo en una colección. Mientras la computadora admita este conjunto de caracteres, puede mostrar todos los caracteres, y no habrá ningún código confuso nuevamente.
Comienza en 0 y especifica un número para cada símbolo, que se llama "CodePoint". Por ejemplo, el símbolo del punto de código 0 es nulo (indica que todos los bits binarios son 0).
Copie el código de la siguiente manera: U+0000 = NULL
En la fórmula anterior, U+ significa que el número hexadecimal inmediatamente siguiente es el punto de código de Unicode.
En la actualidad, la última versión de Unicode es la versión 7.0, con un total de 109,449 símbolos, de los cuales 74,500 están incluidos en los personajes chinos, japoneses y coreanos. Se puede creer aproximadamente que más de dos tercios de los símbolos existentes en el mundo provienen de personajes de Asia Oriental. Por ejemplo, el punto de código para el "bien" chino es hexadecimal 597d.
Copie el código de la siguiente manera: U+597d = OK
Con tantos símbolos, Unicode no se define al mismo tiempo, sino una definición de partición. Cada área puede almacenar 65,536 (216) caracteres, llamados avión. Actualmente, hay 17 (25) planos en total, lo que significa que el tamaño de todo el conjunto de caracteres Unicode ahora es 221.
Los primeros bits de caracteres 65536 se denominan plano básico (BMP abreviado), y sus puntos de código varían de 0 a 216-1. Escrito en hexadecimal es de u+0000 a u+ffff. Todos los caracteres más comunes se colocan en este plano, que es el primer plano que Unicode define y publica.
Los caracteres restantes se colocan en el plano auxiliar (SMP abreviado), y los puntos de código varían de U+010000 a U+10ffff.
2. UTF-32 y UTF-8
Unicode solo especifica el punto de código de cada carácter. Qué tipo de orden de byte se usa para representar este punto de código, que implica el método de codificación.
El método de codificación más intuitivo es que cada punto de código está representado por cuatro bytes, y el contenido de bytes corresponde al punto de código uno por uno. Este método de codificación se llama UTF-32. Por ejemplo, el punto de código 0 está representado por cuatro bytes de 0, y el punto de código 597D se agrega con dos bytes de 0 al frente.
Copie el código de la siguiente manera: U+0000 = 0x0000 0000u+597d = 0x0000 597d
La ventaja de UTF-32 es que las reglas de conversión son simples e intuitivas y la eficiencia de búsqueda es alta. La desventaja es que es espacio desperdiciado, y el texto en inglés con el mismo contenido será cuatro veces mayor que la codificación ASCII. Esta desventaja es fatal, lo que da como resultado que nadie use este método de codificación. El estándar HTML5 estipula explícitamente que las páginas web no deben codificarse en UTF-32.
Lo que la gente realmente necesita es un método de codificación de ahorro de espacio, que condujo al nacimiento de UTF-8. UTF-8 es un método de codificación de longitud variable, con longitudes de caracteres que van desde 1 byte a 4 bytes. Los caracteres más utilizados, más cortos son los bytes. Los primeros 128 caracteres están representados solo por 1 byte, que es exactamente lo mismo que el código ASCII.
Bytes de rango de números 0x0000 - 0x007f10x0080 - 0x07ff20x0800 - 0xfffff30x010000 - 0x10ffff4
Debido a la función de ahorro de espacio de UTF-8, se ha convertido en la codificación web más común en Internet. Sin embargo, tiene poco que ver con el tema de hoy, por lo que no lo haré. Para el método de transcodificación específico, consulte "Notas de codificación de caracteres" que escribí hace muchos años.
Iii. Introducción a UTF-16
La codificación UTF-16 está entre UTF-32 y UTF-8, y combina las características de dos métodos de codificación: longitud fija y longitud variable.
Sus reglas de codificación son simples: los caracteres en el plano básico ocupan 2 bytes, y los caracteres en el plano auxiliar ocupan 4 bytes. Es decir, la longitud de codificación de UTF-16 es 2 bytes (U+0000 a U+FFFF) o 4 bytes (U+010000 a U+10ffff).
Entonces, hay una pregunta: cuando encontramos dos bytes, ¿cómo vemos que es un personaje en sí, o necesitamos interpretarlo con los otros dos bytes?
Es muy inteligente y no sé si fue intencional. En el plano básico, desde u+d800 hasta u+dfff es un segmento vacío, es decir, estos puntos de código no corresponden a ningún caracteres. Por lo tanto, este segmento vacío se puede usar para asignar caracteres del plano auxiliar.
Específicamente, hay 220 bits de caracteres en el plano auxiliar, lo que significa que se requieren al menos 20 bits binarios para estos caracteres. UTF-16 divide estos 20 bits por la mitad. Los primeros 10 bits se asignan en U+D800 a U+DBFF (tamaño del espacio 210), que se llama Bit High (H), y los últimos 10 bits se asignan en U+DC00 a U+DFFF (tamaño del espacio 210), que se llama Bit (L). Esto significa que un personaje de un plano auxiliar se divide en dos planos básicos de representaciones de carácter.
Por lo tanto, cuando encontramos dos bytes y encontramos que su punto de código está entre U+D800 y U+DBFF, podemos concluir que el punto de código inmediatamente después de los dos bytes debe estar entre U+DC00 y U+DFFF. Estos cuatro bytes deben interpretarse juntos.
IV. Fórmula de transcodificación UTF-16
Al convertir los puntos de código Unicode en UTF-16, primero distinga si este es un carácter plano básico o un carácter plano auxiliar. Si es el primero, convierta directamente el punto de código en la forma hexadecimal correspondiente, con una longitud de dos bytes.
Copie el código de la siguiente manera: U+597d = 0x597d
Si es un carácter plano auxiliar, Unicode versión 3.0 ofrece una fórmula de transcodificación.
Copie el código del código de la siguiente manera: H = Math.floor ((C -0x10000) / 0x400) + 0xd800l = (C - 0x10000) % 0x400 + 0xdc00
Tomando un personaje como ejemplo, es un carácter de plano auxiliar con un punto de código U+1D306. El proceso de cálculo de convertirlo en UTF-16 es el siguiente.
Copie el código del código de la siguiente manera: H = Math.floor ((0x1d306-0x10000)/0x400)+0xd800 = 0xd834l = (0x1d306-0x10000) % 0x400+0xdc00 = 0xdf06
Por lo tanto, la codificación UTF-16 del personaje es 0xd834 df06, con una longitud de cuatro bytes.
5. ¿Qué codificación se usa en JavaScript?
El lenguaje JavaScript utiliza conjuntos de caracteres Unicode, pero solo admite un método de codificación.
Esta codificación no es UTF-16, ni UTF-8, ni UTF-32. JavaScript no utiliza los métodos de codificación anteriores.
¡JavaScript usa UCS-2!
VI. Codificación de UCS-2
¿Por qué apareció un UCS-2 repentinamente? Esto requiere un poco de historia.
En la época en que Internet aún no había aparecido, había dos equipos que querían crear un conjunto de personajes unificados. Uno es el equipo de Unicode establecido en 1988, y el otro es el equipo de UCS establecido en 1989. Cuando descubrieron la existencia del otro, rápidamente llegaron a un acuerdo: no hay necesidad de dos conjuntos de personajes unificados en el mundo.
En octubre de 1991, los dos equipos decidieron fusionar el conjunto de personajes. En otras palabras, solo se lanzará un conjunto de conjuntos de caracteres a partir de ahora, que es Unicode, y los conjuntos de caracteres lanzados previamente serán revisados, y los puntos de código de UCS serán exactamente los mismos que Unicode.
El progreso del desarrollo de UCS es más rápido que Unicode. En 1990, se anunció el primer método de codificación UCS-2, utilizando 2 bytes para representar caracteres con puntos de código. (En ese momento, solo había un avión, que era el avión básico, por lo que 2 bytes era suficiente). La codificación UTF-16 no se anunció hasta julio de 1996, y se anunció claramente que era un superconjunto de UCS-2, es decir, los personajes del avión básico fueron codificados por UCS-2, y los personajes del avión auxiliar definieron un método de representación de 4 bítes.
En pocas palabras, la relación entre los dos es que UTF-16 reemplaza UCS-2, o UCS-2 está integrado en UTF-16. Entonces, ahora solo hay UTF-16, no UCS-2.
7. Los antecedentes de nacimiento de JavaScript
Entonces, ¿por qué JavaScript no elige el UTF-16 más avanzado, sino que usa el ya obsoleto UCS-2?
La respuesta es muy simple: no es que no quieras, es que no puedes. Porque cuando apareció el lenguaje JavaScript, no hubo codificación UTF-16.
En mayo de 1995, Brendan Eich diseñó el lenguaje JavaScript en 10 días; En octubre, se lanzó la primera explicación del motor; En noviembre del año siguiente, Netscape presentó oficialmente estándares de lenguaje a ECMA (ver "El nacimiento de JavaScript" para obtener detalles sobre todo el proceso). Al comparar la fecha de lanzamiento de UTF-16 (julio de 1996), comprenderá que Netscape no tenía otra opción en ese momento, ¡solo estaba disponible el método de codificación UCS-2!
8. Limitaciones de las funciones de personajes de JavaScript
Dado que JavaScript solo puede manejar la codificación de UCS-2, todos los caracteres son 2 bytes en este idioma. Si son 4 bytes, serán tratados como dos bytes dobles. Las funciones de personajes de JavaScript se ven afectadas por esto y no pueden devolver el resultado correcto.
Tome los personajes como ejemplo, su codificación UTF-16 es de 4 bytes 0xd834df06. El problema es que la codificación de 4 bytes no pertenece a UCS-2, y JavaScript no lo reconoce, y solo lo considerará dos caracteres separados U+D834 y U+DF06. Como se mencionó anteriormente, estos dos puntos de código están vacíos, por lo que JavaScript los considerará cadenas compuestas por dos personajes vacíos.
El código anterior indica que JavaScript cree que la longitud del carácter es 2, el primer carácter obtenido es un carácter nulo, y el punto de código del primer carácter obtenido es 0xdB34. ¡Estos resultados no son correctos!
Para resolver este problema, debe juzgar el punto de código y luego ajustarlo manualmente. La siguiente es la forma correcta de escribir una cadena.
Copie el código del código de la siguiente manera: WHIEN (++ índice <longitud) {// ... if (charcode> = 0xd800 && charcode <= 0xdbff) {output.push (caracteres+string.charat (++ index)); } else {output.push (carácter); }}
El código anterior indica que al atravesar la cadena, debe hacer un juicio sobre el punto de código. Mientras caiga en el intervalo entre 0xd800 y 0xdbff, debe leerse junto con los siguientes 2 bytes.
Existen problemas similares en todas las funciones de manipulación de personajes de JavaScript.
String.prototype.replace ()
String.prototype.substring ()
String.prototype.slice ()
...
Todas las funciones anteriores son válidas solo para puntos de código de 2 bytes. Para procesar correctamente los puntos de código de 4 bytes, debe implementar su propia versión uno por uno y juzgar el rango de punto de código del carácter actual.
9. ECMAScript 6
La próxima versión de JavaScript, ECMAScript 6 (ES6 para abreviar), ha mejorado enormemente el soporte de Unicode, básicamente resolviendo este problema.
(1) Identificar correctamente los caracteres
ES6 puede reconocer automáticamente los puntos de código de 4 bytes. Por lo tanto, es mucho más fácil atravesar cuerdas.
Copie el código de la siguiente manera: para (Let S of String) {// ...}
Sin embargo, para mantener la compatibilidad, el atributo de longitud sigue siendo el comportamiento original. Para obtener la longitud correcta de la cadena, puede usar el siguiente método.
Copie el código de la siguiente manera: Array.From (String) .length
(2) Representación del punto de código
JavaScript permite que los caracteres de Unicode se representen directamente con los puntos de código, que se escribe como "Puntos de código Back -stain + U +".
Copie el código de la siguiente manera: 'OK' === '/U597D' // Verdadero
Sin embargo, esta notación no es válida para los puntos de código de 4 bytes. ES6 solucionó este problema y podría identificarlo correctamente siempre que los puntos de código se coloquen en aparatos ortopédicos.
(3) Función de procesamiento de cadenas
ES6 ha agregado varias funciones nuevas que tratan específicamente con puntos de código de 4 bytes.
String.FromCodePoint (): Devuelve el carácter correspondiente desde el punto de código Unicode
String.prototype.codePointat (): devuelva el punto de código correspondiente del carácter
String.prototype.at (): devuelve el carácter en la posición dada de la cadena
(4) Expresión regular
ES6 proporciona el modificador U para agregar puntos de código de 4 bytes a expresiones regulares.
(5) Regularización unicode
Algunos personajes tienen símbolos adicionales además de letras. Por ejemplo, en el pinyin chino, el tono de la letra es un símbolo adicional. Los símbolos de tono son muy importantes para muchos idiomas europeos.
Unicode proporciona dos métodos de representación. Uno es un solo carácter con símbolos adicionales, es decir, un punto de código representa un carácter, como el punto de código de ǒ es u+01d1; El otro es usar el símbolo adicional como punto de código y mostrarlo en combinación con el personaje principal, es decir, dos puntos de código representan un carácter, como ǒ se puede escribir como O (U+004f)+ˇ (U+030C).
Copie el código de la siguiente manera: // Método 1 '/U01D1' // 'ǒ' // Método 2 '/u004f/u030c' // 'ǒ'
Estos dos métodos de representación son exactamente los mismos en visión y semántica y deben tratarse como situaciones equivalentes. Sin embargo, JavaScript no puede decir.
Copie el código de la siguiente manera: '/U01D1' === '/U004F/U030C' // FALSO
ES6 proporciona un método normalizar, que permite la "regularización unicode", es decir, convertir los dos métodos en la misma secuencia.
Copie el código de la siguiente manera: '/u01d1'.normalisal () ===' /u004f/u030c'.normaly () // true
Para obtener más introducción a ES6, consulte "Entretenimiento de ECMAScript 6".