1。Unicodeとは何ですか?
Unicodeは、非常にシンプルなアイデアから生まれました。コレクションに世界のすべてのキャラクターを含めることです。コンピューターがこのキャラクターセットをサポートしている限り、すべての文字を表示でき、二度とコードはありません。
0から始まり、「コードポイント」と呼ばれる各シンボルの数値を指定します。たとえば、コードポイント0のシンボルはnullです(すべてのバイナリビットが0であることを示します)。
次のようにコードをコピーします:u+0000 = null
上記の式では、u+は、次の六分位数がユニコードのコードポイントであることを意味します。
現在、Unicodeの最新バージョンはバージョン7.0で、合計109,449のシンボルがあり、そのうち74,500は中国語、日本、韓国のキャラクターに含まれています。世界の既存のシンボルの3分の2以上が東アジアのキャラクターから来ているとほぼ信じられています。たとえば、中国の「良い」のコードポイントは16進597dです。
次のようにコードをコピーします:u+597d = ok
非常に多くのシンボルを使用すると、Unicodeは一度に定義されていませんが、パーティション定義が定義されています。各エリアは、平面と呼ばれる65,536(216)の文字を保存できます。現在、合計で17の平面があります。つまり、ユニコード文字セット全体のサイズが221になります。
最初の65536文字ビットは基本面(BMPの略語)と呼ばれ、そのコードポイントは0〜216-1の範囲です。 16進数で書かれているのは、u+0000からu+ffffまでです。最も一般的なキャラクターはすべてこの平面に配置されます。これは、Unicodeが定義および公開する最初の平面です。
残りの文字は、補助平面(SMPの短縮)に配置され、コードポイントはU+010000からU+10FFFFまでの範囲です。
2。UTF-32およびUTF-8
Unicodeは、各文字のコードポイントのみを指定します。このコードポイントを表すために使用されるバイト順序の種類は、エンコードメソッドを含むものです。
最も直感的なエンコーディング方法は、各コードポイントが4バイトで表され、バイトコンテンツがコードポイントに1つずつ対応することです。このエンコード方法は、UTF-32と呼ばれます。たとえば、コードポイント0は0の4バイトで表され、コードポイント597Dが前に2バイトの0で追加されます。
コードを次のようにコピーします:u+0000 = 0x0000 0000u+597d = 0x0000 597d
UTF-32の利点は、変換ルールがシンプルで直感的であり、検索効率が高いことです。不利な点は、それが無駄なスペースであり、同じコンテンツを持つ英語のテキストはASCIIエンコードの4倍大きくなることです。この欠点は致命的であり、実際にこのエンコード方法を使用していません。 HTML5標準は、WebページをUTF-32にエンコードしてはならないことを明示的に規定しています。
人々が本当に必要としているのは、UTF-8の誕生につながった空間節約コーディング方法です。 UTF-8は、1バイトから4バイトの範囲の文字の長さを持つ可変長さのエンコード法です。より一般的に使用される文字の方が、バイトが短くなります。最初の128文字は1バイトのみで表されますが、これはASCIIコードとまったく同じです。
番号範囲バイト0x0000-0x007f10x0080-0x07ff20x0800-0xfff30x010000-0x10ffff4
UTF-8のスペース節約機能により、インターネット上で最も一般的なWebエンコードになりました。しかし、それは今日のトピックとはほとんど関係がないので、私はそれには入りません。特定のトランスコーディング方法については、何年も前に書いた「文字エンコードノート」を参照してください。
iii。 UTF-16の紹介
UTF-16エンコーディングはUTF-32とUTF-8の間であり、2つのエンコード方法の特性を組み合わせています:固定長と可変長。
そのエンコードルールは単純です。基本面の文字は2バイトを占め、補助平面の文字は4バイトを占めます。つまり、UTF-16のエンコード長は2バイト(U+0000からU+FFFF)または4バイト(U+010000からU+10FFFF)です。
質問があります。2つのバイトに遭遇したとき、それがキャラクター自体であることをどのように確認しますか、それとも他の2バイトで解釈する必要がありますか?
それは非常に賢く、それが意図的であるかどうかはわかりません。基本面では、u+d800からu+dfffまでの空のセグメントです。つまり、これらのコードポイントは文字に対応していません。したがって、この空のセグメントを使用して、補助面の文字をマッピングできます。
具体的には、補助面には220文字のビットがあります。つまり、これらの文字には少なくとも20のバイナリビットが必要です。 UTF-16は、これらの20ビットを半分に分割します。最初の10ビットは、u+d800からu+dbff(スペースサイズ210)でマッピングされます。これは高ビット(h)と呼ばれ、最後の10ビットはu+dc00からu+dfff(スペースサイズ210)でマッピングされ、低ビット(l)と呼ばれます。これは、補助平面の特性が、文字表現の2つの基本的な平面に分割されることを意味します。
したがって、2つのバイトに遭遇し、そのコードポイントがu+d800とu+dbffの間にあることがわかった場合、2つのバイトの直後のコードポイントはu+dc00とu+dfffの間である必要があると結論付けることができます。これらの4つのバイトは一緒に解釈する必要があります。
IV。 UTF-16トランスコーディング式
UnicodeコードポイントをUTF-16に変換する場合、これが基本的なフラット文字か補助フラット文字であるかを区別します。前者の場合、コードポイントを2バイトの長さで対応する16進形式に直接変換します。
次のようにコードをコピーします:u+597d = 0x597d
補助フラット文字の場合、Unicodeバージョン3.0はトランスコーディング式を提供します。
コードコードを次のようにコピーします。h= math.floor((c -0x10000) / 0x400) + 0xd800l =(c -0x10000)%0x400 + 0xdc00
キャラクターを例にとると、それはコードポイントu+1d306を備えた補助平面文字です。 UTF-16に変換する計算プロセスは次のとおりです。
コードコードを次のようにコピーします。h= math.floor((0x1d306-0x10000)/0x400)+0xd800 = 0xd834l =(0x1d306-0x10000)%0x400+0xdc00 = 0xdf06
したがって、文字のUTF-16エンコードは0xD834 DF06で、長さは4バイトです。
5. JavaScriptで使用されるエンコーディングはどれですか?
JavaScript言語はUnicode文字セットを使用しますが、1つのエンコーディング方法のみをサポートします。
このエンコードは、UTF-16ではなくUTF-8、UTF-32でもありません。 JavaScriptは、上記のエンコードメソッドを使用しません。
JavaScriptはUCS-2を使用します!
vi。 UCS-2エンコーディング
なぜUCS-2が突然現れたのですか?これには少しの歴史が必要です。
インターネットがまだ登場していなかった時代には、両方とも統一されたキャラクターセットを作成したいと考えていた2つのチームがありました。 1つは1988年に設立されたUnicodeチームで、もう1つは1989年に設立されたUCSチームです。お互いの存在を発見したとき、彼らはすぐに合意に達しました。世界に2つの統一されたキャラクターセットは必要ありません。
1991年10月、2つのチームはキャラクターセットをマージすることを決定しました。言い換えれば、これはUnicodeであるこれから1つの文字セットのみがリリースされ、以前にリリースされた文字セットが改訂され、UCSのコードポイントはUnicodeとまったく同じです。
UCSの開発の進行は、Unicodeよりも速いです。 1990年に、最初のエンコーディング方法UCS-2が発表され、2バイトを使用してコードポイントの文字を表しました。 (当時、基本的な平面である平面は1つしかなかったため、2バイトで十分でした。)UTF-16エンコーディングは1996年7月まで発表されておらず、UCS-2のスーパーセットであることが明確に発表されました。
簡単に言えば、2つの関係は、UTF-16がUCS-2を置き換えるか、UCS-2がUTF-16に統合されていることです。したがって、今ではUTF-16のみ、UCS-2はありません。
7。JavaScriptの出生背景
それでは、なぜJavaScriptはより高度なUTF-16を選択しないのに、すでに時代遅れのUCS-2を使用しているのでしょうか?
答えは非常に簡単です。それはあなたがしたくないということではなく、できないということです。 JavaScript言語が表示されたとき、UTF-16エンコーディングがなかったからです。
1995年5月、ブレンダンアイヒは10日間でJavaScript言語を設計しました。 10月に、最初の説明エンジンがリリースされました。翌年の11月、Netscapeは正式に言語基準をECMAに提出しました(プロセス全体の詳細については、「JavaScriptの誕生」を参照)。 UTF-16(1996年7月)のリリース日を比較することにより、Netscapeにはその時点で他の選択肢がなかったことがわかります。UCS-2エンコード方法のみが利用可能でした!
8。JavaScript文字関数の制限
JavaScriptはUCS-2エンコードのみを処理できるため、すべての文字はこの言語で2バイトです。それらが4バイトの場合、それらは2つのダブルバイトとして扱われます。 JavaScriptのキャラクター関数はこれの影響を受け、正しい結果を返すことができません。
例として文字を取ります。そのUTF-16エンコードは4バイト0xD834DF06です。問題は、4バイトのエンコードがUCS-2に属していないことであり、JavaScriptはそれを認識しておらず、2つの別々の文字U+D834およびU+DF06のみと見なすことです。前述のように、これらの2つのコードポイントは空であるため、JavaScriptは2つの空の文字で構成される文字列と見なされます。
上記のコードは、JavaScriptが文字の長さが2であると考えていることを示しています。最初の文字はnull文字であり、得られた最初の文字のコードポイントは0xdb34です。これらの結果は正しくありません!
この問題を解決するには、コードポイントについて判断を下し、手動で調整する必要があります。以下は、文字列を書く正しい方法です。
コードコードを次のようにコピーします:while(++ index <length){// ... if(charcode> = 0xd800 && charcode <= 0xdbff){output.push(character+string.charat(++ index)); } else {output.push(文字); }}
上記のコードは、文字列を通過するときにコードポイントで判断を下す必要があることを示しています。 0xD800と0xDBFFの間の間隔に収まる限り、次の2バイトと一緒に読み取る必要があります。
すべてのJavaScript文字操作関数にも同様の問題が存在します。
string.prototype.replace()
string.prototype.substring()
string.prototype.slice()
...
上記のすべての機能は、2バイトのコードポイントのみで有効です。 4バイトのコードポイントを正しく処理するには、独自のバージョンを1つずつ展開し、現在の文字のコードポイント範囲を判断する必要があります。
9。ECMascript6
JavaScriptの次のバージョンであるECMAScript 6(ES6略で)は、ユニコードサポートを大幅に強化し、基本的にこの問題を解決しました。
(1)文字を正しく識別します
ES6は、4バイトのコードポイントを自動的に認識できます。したがって、文字列を通過する方がはるかに簡単です。
次のようにコードをコピーします:(文字列のs){// ...}
ただし、互換性を維持するために、長さの属性は依然として元の動作です。文字列の正しい長さを取得するには、次の方法を使用できます。
コードを次のようにコピーします:array.from(string).length
(2)コードポイント表現
JavaScriptを使用すると、Unicode文字を「BackSlash + U + Code Points」と書かれているコードポイントで直接表現できます。
次のようにコードをコピーします: 'ok' === '/u597d' // true
ただし、この表記は4バイトのコードポイントで無効です。 ES6はこの問題を修正し、コードポイントが巻き毛装具に配置されている限り、それを正しく識別できます。
(3)文字列処理関数
ES6は、4バイトのコードポイントを特に扱ういくつかの新しい機能を追加しました。
string.fromCodePoint():Unicodeコードポイントから対応する文字を返します
string.prototype.codepointat():文字から対応するコードポイントを返します
string.prototype.at():文字列の指定された位置で文字を返します
(4)正規表現
ES6は、4バイトのコードポイントを正規表現に追加するためのUモディファイアを提供します。
(5)Unicode Remulization
一部の文字には、文字に加えて追加のシンボルがあります。たとえば、中国のピニインでは、文字のトーンは追加のシンボルです。トーンシンボルは、多くのヨーロッパの言語にとって非常に重要です。
Unicodeは2つの表現方法を提供します。 1つは、追加のシンボルを持つ単一の文字です。つまり、コードポイントは、ǒのコードポイントなどの文字を表します。もう1つは、追加のシンボルをコードポイントとして使用し、メインキャラクターと組み合わせて表示することです。つまり、o(u+004f)+ˇ(u+030c)として記述できるなど、2つのコードポイントを表します。
コードを次のようにコピーします://方法1 '/u01d1' // 'ǒ' //方法2 '/u004f/u030c' // 'ǒ' '
これらの2つの表現方法は、ビジョンとセマンティクスでまったく同じであり、同等の状況として扱う必要があります。ただし、JavaScriptはわかりません。
次のようにコードをコピーします: '/u01d1' === '/u004f/u030c' // false
ES6は正規化方法を提供し、「Unicode Remulization」、つまり2つのメソッドを同じシーケンスに変換することを可能にします。
コードを次のようにコピーします: '/u01d1'.normalize()==='/u004f/u030c'.normalize()// true
ES6の詳細については、「Ectentation of Ecmascript 6」を参照してください。