1. Qu'est-ce que Unicode?
Unicode est originaire d'une idée très simple: inclure tous les personnages du monde dans une collection. Tant que l'ordinateur prend en charge ce jeu de caractères, il peut afficher tous les caractères et il n'y aura plus de code brouillé.
Il commence à 0 et spécifie un nombre pour chaque symbole, qui est appelé "codepoint". Par exemple, le symbole du point de code 0 est nul (indique que tous les bits binaires sont 0).
Copiez le code comme suit: U + 0000 = null
Dans la formule ci-dessus, U + signifie que le numéro hexadécimal immédiatement suivant est le point de code d'Unicode.
À l'heure actuelle, la dernière version d'Unicode est la version 7.0, avec un total de 109 449 symboles, dont 74 500 sont inclus dans des personnages chinois, japonais et coréens. On peut croire approximativement que plus des deux tiers des symboles existants dans le monde proviennent de personnages d'Asie de l'Est. Par exemple, le point de code pour le «bien» chinois est hexadécimal 597d.
Copiez le code comme suit: u + 597d = ok
Avec autant de symboles, Unicode n'est pas défini en même temps, mais la définition de partition. Chaque zone peut stocker 65 536 (216) caractères, appelée avion. Actuellement, il y a 17 (25) plans au total, ce qui signifie que la taille de l'ensemble du jeu de caractères Unicode est désormais 221.
Les 65536 bits de caractères sont appelés plan de base (BMP abrégé), et leurs points de code varient de 0 à 216-1. Écrit en hexadécimal est de U + 0000 à u + ffff. Tous les caractères les plus courants sont placés dans ce plan, qui est le premier plan qu'Unicode définit et publie.
Les caractères restants sont placés dans le plan auxiliaire (SMP abrégé) et les points de code varient de U + 010000 à U + 10FFFF.
2. UTF-32 et UTF-8
Unicode spécifie uniquement le point de code de chaque caractère. Quel type d'ordre d'octet est utilisé pour représenter ce point de code, qui implique la méthode de codage.
La méthode d'encodage la plus intuitive est que chaque point de code est représenté par quatre octets, et le contenu d'octet correspond au point de code un par un. Cette méthode d'encodage est appelée UTF-32. Par exemple, le point de code 0 est représenté par quatre octets de 0, et le point de code 597D est ajouté avec deux octets de 0 devant.
Copiez le code comme suit: U + 0000 = 0x0000 0000U + 597D = 0x0000 597D
L'avantage de l'UTF-32 est que les règles de conversion sont simples et intuitives et que l'efficacité de recherche est élevée. L'inconvénient est qu'il s'agit de l'espace gaspillé et que le texte anglais avec le même contenu sera quatre fois plus grand que le codage ASCII. Cet inconvénient est fatal, ce qui ne fait que personne n'utilisant réellement cette méthode de codage. La norme HTML5 stipule explicitement que les pages Web ne doivent pas être codées en UTF-32.
Ce dont les gens ont vraiment besoin, c'est une méthode de codage d'économie d'espace, qui a conduit à la naissance de l'UTF-8. UTF-8 est une méthode de codage de longueur variable, avec des longueurs de caractère allant de 1 octet à 4 octets. Plus les caractères les plus couramment utilisés, plus les octets sont courts. Les 128 premiers caractères sont représentés par seulement 1 octet, ce qui est exactement le même que le code ASCII.
Numéro Range octets 0x0000 - 0x007f10x0080 - 0x07ff20x0800 - 0xfff30x010000 - 0x10ffff4
En raison de la fonction d'économie d'espace de l'UTF-8, il est devenu le codage Web le plus courant sur Internet. Cependant, cela n'a pas grand-chose à voir avec le sujet d'aujourd'hui, donc je n'y vais pas. Pour la méthode de transcodage spécifique, veuillez vous référer à "Notes d'encodage des caractères" que j'ai écrites il y a de nombreuses années.
Iii. Introduction à UTF-16
Le codage UTF-16 se situe entre UTF-32 et UTF-8, et il combine les caractéristiques de deux méthodes de codage: longueur fixe et longueur variable.
Ses règles d'encodage sont simples: les caractères du plan de base occupent 2 octets et les caractères du plan auxiliaire occupent 4 octets. C'est-à-dire que la longueur de codage de l'UTF-16 est soit de 2 octets (U + 0000 à U + FFFF) ou de 4 octets (U + 010000 à U + 10FFFF).
Il y a donc une question: lorsque nous rencontrons deux octets, comment voyons-nous qu'il s'agit d'un personnage lui-même, ou devons-nous l'interpréter avec les deux autres octets?
C'est très intelligent et je ne sais pas si c'était intentionnel. Dans le plan de base, de U + D800 à U + DFFF est un segment vide, c'est-à-dire que ces points de code ne correspondent à aucun caractères. Par conséquent, ce segment vide peut être utilisé pour cartographier les caractères du plan auxiliaire.
Plus précisément, il y a 220 bits de caractères dans le plan auxiliaire, ce qui signifie qu'au moins 20 bits binaires sont nécessaires pour ces caractères. L'UTF-16 divise ces 20 bits en deux. Les 10 premiers bits sont mappés en U + D800 en U + DBFF (taille de l'espace 210), qui est appelé bit haut (H), et les 10 derniers bits sont mappés en U + DC00 en U + DFFF (taille de l'espace 210), qui est appelé le bit bas (L). Cela signifie qu'un caractère d'un plan auxiliaire est divisé en deux plans de base de représentations de caractère.
Par conséquent, lorsque nous rencontrons deux octets et constatons que son point de code se situe entre U + D800 et U + DBFF, nous pouvons conclure que le point de code immédiatement suivant les deux octets devrait être entre U + DC00 et U + DFFF. Ces quatre octets doivent être interprétés ensemble.
Iv. Formule transcodante UTF-16
Lors de la conversion du code Unicode pointe en UTF-16, distinguez d'abord s'il s'agit d'un caractère plat de base ou d'un caractère plat auxiliaire. S'il s'agit du premier, convertissez directement le point de code en forme hexadécimale correspondante, avec une longueur de deux octets.
Copiez le code comme suit: u + 597d = 0x597d
S'il s'agit d'un caractère plat auxiliaire, Unicode version 3.0 donne une formule transcodante.
Copiez le code du code comme suit: h = math.floor ((C-0x10000) / 0x400) + 0xd800l = (C - 0x10000)% 0x400 + 0xdc00
Prenant un caractère comme exemple, il s'agit d'un caractère de plan auxiliaire avec un point de code U + 1d306. Le processus de calcul de la conversion en UTF-16 est le suivant.
Copiez le code du code comme suit: h = math.floor ((0x1d306-0x10000) / 0x400) + 0xd800 = 0xd834l = (0x1d306-0x10000)% 0x400 + 0xdc00 = 0xdf06
Par conséquent, le codage UTF-16 du caractère est 0xd834 DF06, avec une longueur de quatre octets.
5. Quel codage est utilisé dans JavaScript?
Le langage JavaScript utilise des ensembles de caractères Unicode, mais ne prend en charge qu'une méthode d'encodage.
Ce codage n'est ni UTF-16, ni UTF-8, ni UTF-32. JavaScript n'utilise pas les méthodes d'encodage ci-dessus.
JavaScript utilise UCS-2!
Vi. Encodage UCS-2
Pourquoi un UCS-2 est-il apparu soudainement? Cela nécessite un peu d'histoire.
À l'époque où Internet n'était pas encore apparu, il y avait deux équipes qui voulaient tous deux créer un jeu de personnage unifié. L'un est l'équipe Unicode créée en 1988, et l'autre est l'équipe de l'UCS créée en 1989. Lorsqu'ils ont découvert l'existence de l'autre, ils ont rapidement conclu un accord: il n'y a pas besoin de deux jeux de personnages unifiés au monde.
En octobre 1991, les deux équipes ont décidé de fusionner le jeu de personnages. En d'autres termes, un seul ensemble de jeux de caractères sera publié à partir de maintenant, qui est Unicode, et les ensembles de caractères publiés précédemment seront révisés, et les points de code des UCS seront exactement les mêmes que Unicode.
La progression du développement de l'UCS est plus rapide qu'Unicode. En 1990, la première méthode d'encodage UCS-2 a été annoncée, en utilisant 2 octets pour représenter des caractères avec des points de code. (À ce moment-là, il n'y avait qu'un seul avion, qui était le plan de base, donc 2 octets étaient suffisants.) Le codage UTF-16 n'a été annoncé qu'en juillet 1996, et il a été clairement annoncé qu'il s'agissait d'un superset de UCS-2, c'est-à-dire des caractères de base de plan de base par UCS-2, et les personnages d'avion axiliaire défini une méthode de représentation de 4 octets.
En termes simples, la relation entre les deux est que l'UTF-16 remplace UCS-2, ou UCS-2 est intégré dans UTF-16. Donc, maintenant il n'y a que UTF-16, pas UCS-2.
7. Le contexte de la naissance de JavaScript
Alors, pourquoi JavaScript ne choisit-il pas l'UTF-16 plus avancé, mais utilise le UCS-2 déjà obsolète?
La réponse est très simple: ce n'est pas que vous ne voulez pas, c'est que vous ne pouvez pas. Parce que lorsque la langue JavaScript est apparue, il n'y avait pas de codage UTF-16.
En mai 1995, Brendan Eich a conçu la langue javascript en 10 jours; En octobre, le premier moteur d'explication a été publié; En novembre de l'année suivante, NetScape a officiellement soumis les normes linguistiques à l'ECMA (voir "La naissance de JavaScript" pour plus de détails sur l'ensemble du processus). En comparant la date de sortie de l'UTF-16 (juillet 1996), vous comprendrez que Netscape n'avait aucun autre choix à ce moment-là, seule la méthode d'encodage UCS-2 était disponible!
8. Limites des fonctions de caractères JavaScript
Étant donné que JavaScript ne peut gérer que l'encodage UCS-2, tous les caractères sont 2 octets dans cette langue. S'ils sont de 4 octets, ils seront traités comme deux doubles octets. Les fonctions de caractère de JavaScript sont affectées par cela et ne peuvent pas renvoyer le résultat correct.
Prenez des caractères comme exemple, son codage UTF-16 est de 4 octets 0xd834df06. Le problème est que le codage de 4 octets n'appartient pas à UCS-2, et JavaScript ne le reconnaît pas, et ne le considèrera que comme deux caractères distincts U + D834 et U + DF06. Comme mentionné précédemment, ces deux points de code sont vides, donc JavaScript les considérera comme des chaînes composées de deux caractères vides!
Le code ci-dessus indique que JavaScript estime que la longueur du caractère est 2, le premier caractère obtenu est un caractère nul et que le point de code du premier caractère obtenu est 0xdb34. Ces résultats ne sont pas corrects!
Pour résoudre ce problème, vous devez porter un jugement sur le point de code, puis l'ajuster manuellement. Ce qui suit est la bonne façon d'écrire une chaîne.
Copiez le code de code comme suit: while (++ index <longueur) {// ... if (charcode> = 0xd800 && charcode <= 0xdbff) {output.push (caractères + string.charat (++ index)); } else {output.push (caractères); }}
Le code ci-dessus indique que lorsque vous traversez la chaîne, vous devez porter un jugement sur le point de code. Tant qu'il tombe dans l'intervalle entre 0xd800 et 0xdbff, il doit être lu avec les 2 octets suivants.
Des problèmes similaires existent dans toutes les fonctions de manipulation de caractères JavaScript.
String.prototype.replace ()
String.prototype.substring ()
String.prototype.slice ()
...
Toutes les fonctions ci-dessus sont valides pour les points de code de 2 octets uniquement. Pour traiter correctement les points de code de 4 octets, vous devez déployer votre propre version un par un et juger la plage de points de code du caractère actuel.
9. Ecmascript 6
La prochaine version de JavaScript, ECMascript 6 (ES6 pour faire court), a considérablement amélioré le support Unicode, résolvant essentiellement ce problème.
(1) Identifier correctement les caractères
ES6 peut reconnaître automatiquement les points de code de 4 octets. Par conséquent, il est beaucoup plus facile de parcourir les chaînes.
Copiez le code comme suit: pour (Soit S de String) {// ...}
Cependant, afin de maintenir la compatibilité, l'attribut de longueur est toujours le comportement d'origine. Afin d'obtenir la bonne longueur de la chaîne, vous pouvez utiliser la méthode suivante.
Copiez le code comme suit: array.from (string) .length
(2) Représentation du point de code
JavaScript permet à des caractères Unicode d'être représentés directement avec des points de code, qui est écrit "BackSlash + U + Code Points".
Copiez le code comme suit: 'ok' === '/ u597d' // true
Cependant, cette notation n'est pas valide pour les points de code de 4 octets. ES6 a résolu ce problème et pourrait l'identifier correctement tant que les points de code sont placés en accolades bouclées.
(3) Fonction de traitement des chaînes
ES6 a ajouté plusieurs nouvelles fonctions qui traitent spécifiquement des points de code de 4 octets.
String.FromCodePoint (): Renvoyez le caractère correspondant à partir du point de code Unicode
String.prototype.codepointat (): renvoie le point de code correspondant du caractère
String.prototype.at (): renvoie le caractère à la position donnée de la chaîne
(4) Expression régulière
ES6 fournit le modificateur U pour ajouter des points de code de 4 octets aux expressions régulières.
(5) régularisation Unicode
Certains caractères ont des symboles supplémentaires en plus des lettres. Par exemple, dans le pinyin chinois, le ton de la lettre est un symbole supplémentaire. Les symboles de ton sont très importants pour de nombreuses langues européennes.
Unicode fournit deux méthodes de représentation. L'un est un seul caractère avec des symboles supplémentaires, c'est-à-dire qu'un point de code représente un caractère, tel que le point de code de ǒ est U + 01d1; L'autre consiste à utiliser le symbole supplémentaire comme point de code et à l'afficher en combinaison avec le caractère principal, c'est-à-dire que deux points de code représentent un caractère, tel que ǒ peut être écrit comme O (U + 004F) + ˇ (U + 030C).
Copiez le code comme suit: // Méthode 1 '/ u01d1' // 'ǒ' // Méthode 2 '/ u004f / u030c' // 'ǒ'
Ces deux méthodes de représentation sont exactement les mêmes dans la vision et la sémantique et doivent être traitées comme des situations équivalentes. Cependant, JavaScript ne peut pas le dire.
Copiez le code comme suit: '/ u01d1' === '/ u004f / u030c' // false
ES6 fournit une méthode de normalisation, permettant la "régularisation Unicode", c'est-à-dire convertissant les deux méthodes en même séquence.
Copiez le code comme suit: '/u01d1'.normalize () ===' /u004f/U030C'.Normalize () // Vrai
Pour plus d'introduction à ES6, veuillez consulter "Entertainment of Ecmascript 6".