1. Was ist Unicode?
Unicode stammt aus einer sehr einfachen Idee: Alle Charaktere der Welt in eine Sammlung einbeziehen. Solange der Computer dieses Zeichensatz unterstützt, kann er alle Zeichen anzeigen und es gibt keinen verstümmelten Code.
Es beginnt bei 0 und gibt eine Zahl für jedes Symbol an, das als "CodePoint" bezeichnet wird. Zum Beispiel ist das Symbol des Codepunkts 0 null (zeigt an, dass alle binären Bits 0 sind).
Kopieren Sie den Code wie folgt: u+0000 = null
In der obigen Formel bedeutet U+, dass die Hexadezimalzahl unmittelbar nach dem Codepunkt von Unicode ist.
Derzeit ist die neueste Version von Unicode Version 7.0 mit insgesamt 109.449 Symbolen, von denen 74.500 in chinesischen, japanischen und koreanischen Charakteren enthalten sind. Es kann ungefähr angenommen werden, dass mehr als zwei Drittel der vorhandenen Symbole der Welt von ostasiatischen Charakteren stammen. Zum Beispiel ist der Codepunkt für das chinesische "Gut" Hexadezimal 597D.
Kopieren Sie den Code wie folgt: U+597D = OK
Bei so vielen Symbolen ist Unicode nicht zu einer Zeit definiert, sondern eine Partitionsdefinition. Jedes Bereich kann 65.536 (216) Zeichen speichern, als Flugzeug bezeichnet. Derzeit gibt es insgesamt 17 (25) Flugzeuge, was bedeutet, dass die Größe des gesamten Unicode -Zeichensatzes jetzt 221 beträgt.
Die ersten 65536-Zeichenbits werden als Basisebene (abgekürzte BMP) bezeichnet und ihre Codepunkte reichen von 0 bis 216-1. In Hexadezimal geschrieben ist von U+0000 bis U+FFFF. Die häufigsten Zeichen werden in dieser Ebene platziert, die die erste Ebene ist, die Unicode definiert und veröffentlicht.
Die verbleibenden Zeichen werden in der Hilfsebene (abgekürzte SMP) platziert und die Codepunkte reichen von U+010000 bis U+10ffff.
2. UTF-32 und UTF-8
Unicode gibt nur den Codepunkt jedes Zeichens an. Mit welcher Art von Byte -Reihenfolge wird dieser Codepunkt dargestellt, der die Codierungsmethode beinhaltet.
Die intuitivste Codierungsmethode ist, dass jeder Codepunkt durch vier Bytes dargestellt wird und der Byte -Inhalt dem Codepunkt eins nach dem anderen entspricht. Diese Codierungsmethode heißt UTF-32. Zum Beispiel wird der Codepunkt 0 durch vier Bytes von 0 dargestellt, und der Codepunkt 597D wird mit zwei Bytes von 0 vorne hinzugefügt.
Kopieren Sie den Code wie folgt: U+0000 = 0x0000 0000U+597D = 0x0000 597D
Der Vorteil von UTF-32 besteht darin, dass die Conversion-Regeln einfach und intuitiv und die Suchffizienz hoch sind. Der Nachteil ist, dass es sich um einen verschwendeten Raum handelt und der englische Text mit demselben Inhalt viermal größer ist als die ASCII -Codierung. Dieser Nachteil ist tödlich und führt dazu, dass niemand diese Codierungsmethode verwendet. Der HTML5-Standard sieht ausdrücklich fest, dass Webseiten nicht in UTF-32 codiert werden dürfen.
Was die Menschen wirklich brauchen, ist eine platzsparende Codierungsmethode, die zur Geburt von UTF-8 führte. UTF-8 ist eine Codierungsmethode mit variabler Länge mit Zeichenlängen von 1 Byte bis 4 Bytes. Die häufiger verwendeten Zeichen, desto kürzer die Bytes. Die ersten 128 Zeichen werden durch nur 1 Byte dargestellt, was genau dem ASCII -Code entspricht.
Bytes für Zahlenbereich 0x0000 - 0x007f10x0080 - 0x07ff20x0800 - 0xfff30x010000 - 0x10ffff4
Aufgrund der platzsparenden Funktion von UTF-8 ist es zum häufigsten Web-Codieren im Internet geworden. Es hat jedoch wenig mit dem heutigen Thema zu tun, also werde ich nicht darauf eingehen. Für die spezifische Transcodierungsmethode finden Sie in "Character Coding Notes", die ich vor vielen Jahren geschrieben habe.
III. Einführung in UTF-16
Die UTF-16-Codierung erfolgt zwischen UTF-32 und UTF-8 und kombiniert die Eigenschaften zweier Codierungsmethoden: feste Länge und variable Länge.
Die Codierungsregeln sind einfach: Die Zeichen in der Basisebene belegen 2 Bytes und die Zeichen in der Hilfsebene belegen 4 Bytes. Das heißt, die Codierungslänge von UTF-16 beträgt entweder 2 Bytes (U+0000 bis U+FFFF) oder 4 Bytes (U+010000 bis U+10ffff).
Es gibt also eine Frage: Wenn wir zwei Bytes begegnen, wie sehen wir, dass es sich um eine Figur selbst handelt, oder müssen wir sie mit den anderen beiden Bytes interpretieren?
Es ist sehr klug und ich weiß nicht, ob es beabsichtigt war. In der Basisebene ist von U+D800 bis U+DFFF ein leeres Segment, dh diese Codepunkte entsprechen keinen Zeichen. Daher kann dieses leere Segment verwendet werden, um Zeichen der Hilfsebene zu kartieren.
Insbesondere gibt es 220 Zeichen in der Hilfsebene, was bedeutet, dass für diese Zeichen mindestens 20 binäre Bits erforderlich sind. UTF-16 teilt diese 20 Bit in zwei Hälften. Die ersten 10 Bit werden in U+D800 auf U+DBFF (Raumgröße 210) abgebildet, was als Hochbit (H) bezeichnet wird, und die letzten 10 Bit werden in U+DC00 bis U+DFFF (Raumgröße 210) zugeordnet, was als niedriges Bit (L) bezeichnet wird. Dies bedeutet, dass ein Charakter einer Hilfsebene in zwei grundlegende Ebenen von Charakterdarstellungen unterteilt ist.
Wenn wir zwei Bytes begegnen und feststellen, dass sein Codepunkt zwischen U+D800 und U+DBFF liegt, können wir schließen, dass der Codepunkt unmittelbar nach den beiden Bytes zwischen U+DC00 und U+DFFF liegen sollte. Diese vier Bytes müssen gemeinsam interpretiert werden.
Iv. UTF-16 Transcodierungsformel
Unterscheiden Sie beim Konvertieren von Unicode-Codepunkten in UTF-16 zunächst, ob es sich um einen grundlegenden flachen Charakter oder ein flacher Hilfszeichen handelt. Wenn es das erstere ist, konvertieren Sie den Code direkt in die entsprechende hexadezimale Form mit einer Länge von zwei Bytes.
Kopieren Sie den Code wie folgt: u+597d = 0x597d
Wenn es sich um ein hilfsbereites flaches Zeichen handelt, gibt Unicode Version 3.0 eine Transcodierungsformel.
Kopieren Sie den Code -Code wie folgt: H = math.floor ((C -0x10000) / 0x400) + 0xd800L = (c - 0x10000) % 0x400 + 0xdc00
Wenn Sie als Beispiel ein Zeichen nehmen, handelt es sich um ein Hilfsebene -Zeichen mit einem Codepunkt U+1D306. Der Berechnungsprozess der Konvertierung in UTF-16 ist wie folgt.
Kopieren Sie den Code-Code wie folgt: H = Math.floor ((0x1d306-0x10000)/0x400)+0xd800 = 0xd834l = (0x1d306-0x10000) % 0x400+0xdc00 = 0xdf06
Daher beträgt die UTF-16-Codierung des Zeichens 0xD834 DF06 mit einer Länge von vier Bytes.
5. Welche Codierung wird in JavaScript verwendet?
Die JavaScript -Sprache verwendet Unicode -Zeichensätze, unterstützt jedoch nur eine Codierungsmethode.
Diese Codierung ist weder UTF-16 noch UTF-8 noch UTF-32. JavaScript verwendet nicht die obigen Codierungsmethoden.
JavaScript verwendet UCS-2!
Vi. UCS-2-Codierung
Warum erschien plötzlich ein UCS-2? Dies erfordert eine kleine Geschichte.
In der Zeit, in der das Internet noch nicht erschienen war, gab es zwei Teams, die beide ein einheitliches Charakter -Set erstellen wollten. Das eine ist das 1988 gegründete Unicode -Team, und das andere ist das 1989 gegründete UCS -Team. Als sie sich gegenseitig die Existenz des anderen entdeckten, haben sie schnell eine Einigung erzielt: Es besteht keine Notwendigkeit für zwei einheitliche Charakter -Sets in der Welt.
Im Oktober 1991 beschlossen die beiden Teams, den Charakter -Set zusammenzuführen. Mit anderen Worten, von nun an werden nur eine Reihe von Zeichensätzen freigegeben, nämlich Unicode, und die zuvor freigegebenen Zeichensätze werden überarbeitet, und die Codepunkte von UCS sind genau das gleiche wie Unicode.
Der Entwicklungsfortschritt von UCS ist schneller als Unicode. Im Jahr 1990 wurde die erste Codierungsmethode UCS-2 angekündigt, wobei 2 Bytes verwendet wurden, um Zeichen mit Codepunkten darzustellen. (Zu dieser Zeit gab es nur ein Flugzeug, das das Grundflugzeug war, also war 2 Bytes ausreichend.) Die UTF-16-Codierung wurde erst im Juli 1996 bekannt gegeben, und es wurde deutlich bekannt, dass es sich um ein Superet von UCS-2 handelte, dh die von UCS-2 codierte Grundflugzeugfiguren wurden von UCS-2 codiert, und die Definitionen der Axiliary-Flugzeuge, die eine 4-by-Repräsentations-Methode definiert wurden.
Einfach ausgedrückt, die Beziehung zwischen beiden besteht darin, dass UTF-16 UCS-2 ersetzt oder UCS-2 in UTF-16 integriert ist. Jetzt gibt es also nur UTF-16, kein UCS-2.
7. Der Geburtshintergrund von JavaScript
Warum wählt JavaScript nicht die erweiterte UTF-16 aus, sondern verwendet die bereits veraltete UCS-2?
Die Antwort ist sehr einfach: Es ist nicht so, dass Sie es nicht wollen, sondern dass Sie es nicht können. Denn als die JavaScript-Sprache erschien, gab es keine UTF-16-Codierung.
Im Mai 1995 entwarf Brendan Eich die JavaScript -Sprache in 10 Tagen; Im Oktober wurde der erste Erklärungsmotor veröffentlicht; Im November des folgenden Jahres reichte Netscape offiziell Sprachstandards bei ECMA ein (siehe "die Geburt von JavaScript" für den gesamten Prozess). Durch den Vergleich des Veröffentlichungsdatums von UTF-16 (Juli 1996) werden Sie verstehen, dass Netscape zu diesem Zeitpunkt keine andere Wahl hatte, nur die UCS-2-Codierungsmethode verfügbar war!
8. Einschränkungen der JavaScript -Zeichenfunktionen
Da JavaScript nur die UCS-2-Codierung verarbeiten kann, sind alle Zeichen 2 Bytes in dieser Sprache. Wenn es sich um 4 Bytes handelt, werden sie als zwei Doppel -Bytes behandelt. Die Charakterfunktionen von JavaScript sind davon beeinflusst und können nicht das richtige Ergebnis zurückgeben.
Nehmen wir als Beispiel Zeichen, seine UTF-16-Codierung beträgt 4 Bytes 0xD834DF06. Das Problem ist, dass die 4-Byte-Codierung nicht zu UCS-2 gehört, und JavaScript erkennt es nicht und betrachtet es nur als zwei separate Zeichen U+D834 und U+DF06. Wie bereits erwähnt, sind diese beiden Codepunkte leer, sodass JavaScript sie als Zeichenfolgen betrachten, die aus zwei leeren Zeichen bestehen!
Der obige Code zeigt an, dass JavaScript der Ansicht ist, dass die Länge des Zeichens 2 ist, das erste erhaltene Zeichen ist ein Nullzeichen, und der Codepunkt des erhaltenen ersten erhaltenen Zeichens beträgt 0xdb34. Diese Ergebnisse sind nicht korrekt!
Um dieses Problem zu lösen, müssen Sie ein Urteil über den Codepunkt vornehmen und es dann manuell anpassen. Das Folgende ist der richtige Weg, um eine Zeichenfolge zu schreiben.
Kopieren Sie den Code -Code wie folgt: while (++ Index <Länge) {// ... if (charCode> = 0xd800 && charCode <= 0xdbff) {output.push (Zeichen+string.charat (++ Index)); } else {output.push (Zeichen); }}
Der obige Code zeigt an, dass Sie beim Durchqueren der Zeichenfolge ein Urteil über den Codepunkt vornehmen müssen. Solange es in das Intervall zwischen 0xD800 und 0xDBFF fällt, muss es zusammen mit den nächsten 2 Bytes gelesen werden.
Ähnliche Probleme gibt es in allen Manipulationsfunktionen von JavaScript -Charakteren.
String.Prototype.Replace ())
String.Prototype.substring ()
String.Prototype.slice ()
...
Alle oben genannten Funktionen sind nur für 2-Byte-Codepunkte gültig. Um 4-Byte-Codepunkte korrekt zu verarbeiten, müssen Sie Ihre eigene Version 1 nach dem anderen bereitstellen und den Codepunktbereich des aktuellen Zeichens beurteilen.
9. ECMascript 6
Die nächste Version von JavaScript, ECMascript 6 (kurz ES6), hat die Unicode -Unterstützung erheblich verbessert und dieses Problem grundsätzlich gelöst.
(1) Identifizieren Sie Zeichen korrekt
ES6 kann automatisch 4-Byte-Codepunkte erkennen. Daher ist es viel einfacher, Strings zu durchqueren.
Kopieren Sie den Code wie folgt: für (let s der String) {// ...}
Um die Kompatibilität aufrechtzuerhalten, ist das Längenattribut immer noch das ursprüngliche Verhalten. Um die richtige Länge der Zeichenfolge zu erhalten, können Sie die folgende Methode verwenden.
Kopieren Sie den Code wie folgt: array.from (Zeichenfolge) .Length
(2) Codepunktdarstellung
Mit JavaScript können Unicode -Zeichen direkt mit Codepunkten dargestellt werden, die als "Backslash + U + Codepunkte" geschrieben werden.
Kopieren Sie den Code wie folgt: 'OK' === '/U597D' // true
Diese Notation ist jedoch für 4-Byte-Codepunkte ungültig. ES6 hat dieses Problem behoben und konnte es korrekt identifizieren, solange die Codepunkte in lockige Klammern platziert werden.
(3) Funktion der String -Verarbeitungsfunktion
ES6 hat mehrere neue Funktionen hinzugefügt, die sich speziell mit 4-Byte-Codepunkten befassen.
String.FromCodePoint (): Geben Sie das entsprechende Zeichen aus dem Unicode -Codepunkt zurück
String.Prototype.CodePointat (): Geben Sie den entsprechenden Codepunkt aus dem Zeichen zurück
String.Prototype.at (): Gibt das Zeichen an der angegebenen Position der Zeichenfolge zurück
(4) Regelmäßiger Ausdruck
ES6 bietet den U-Modifikator zum Hinzufügen von 4-Byte-Codepunkten zu regulären Ausdrücken.
(5) Unicode -Regularisierung
Einige Zeichen haben zusätzlich zu Buchstaben zusätzliche Symbole. Zum Beispiel ist der Ton auf dem Buchstaben im chinesischen Pinyin ein zusätzliches Symbol. Tonsymbole sind für viele europäische Sprachen sehr wichtig.
Unicode liefert zwei Darstellungsmethoden. Eines ist ein einzelnes Zeichen mit zusätzlichen Symbolen, dh ein Codepunkt stellt ein Zeichen dar, wie z. B. der Codepunkt von ǒ ist U+01D1; Das andere besteht darin, das zusätzliche Symbol als Codepunkt zu verwenden und es in Kombination mit dem Hauptzeichen anzuzeigen, dh zwei Codepunkte repräsentieren ein Zeichen wie ǒ können als o (u+004f)+ˇ (u+030c) geschrieben werden.
Kopieren Sie den Code wie folgt: // Methode 1 '/u01d1' // 'ǒ' // Methode 2 '/u004f/u030c' // 'ǒ' '
Diese beiden Repräsentationsmethoden sind in Sicht und Semantik genau gleich und sollten als äquivalente Situationen behandelt werden. JavaScript kann es jedoch nicht sagen.
Kopieren Sie den Code wie folgt: '/u01d1' === '/u004f/u030c' // false
ES6 liefert eine Normalisierungsmethode, die "Unicode -Regularisierung" ermöglicht, dh die beiden Methoden in dieselbe Sequenz umzuwandeln.
Kopieren Sie den Code wie folgt: '/u01d1'.normalize () ===' /u004f/u030c'.normalize () // true
Weitere Einführung in ES6 finden Sie in "Unterhaltung von ECMascript 6".