unicode

Unicode 是一種全球通用的字元編碼標準,用於交換並顯示主要的書寫語言。

從 0 開始,每個符號指定一個編碼,稱為碼點(code point),例

U+ 後加接16進制的 Unicode 碼點

U+0000 = null

共有17個平面:1個基本平面 16個輔助平面

依編碼方式可區分為 UTF-8、UTF-16、UTF-32。

UTF-32

每個碼點用4個字節表點。註:字節 == byte

U+0000 = 0x0000 0000

U+597D = 0x0000 597D

UTF-8

UTF-8是一種變長的編碼方法,字符長度從1個字節到4個字節不等。

UTF-16 編碼

依長度分為為基本平面(2 字節)或補助平面(4 字節)。

基本平面: 0x0000-0xFFFF

輔助平面: 0x010000-0x10FFFF

設計上輔助平面被拆成兩個基本平面的字符來表示。

前半段在 0xD800-0xDBFF 後半段在 0xDC00-0xDFFF

轉換公式

基本平面

U+597D = 0x597D

輔助平面

H = Math.floor((c-0x10000) / 0x400)+0xD800

L = (c - 0x10000) % 0x400 + 0xDC00

Javascript 實際上用的是 UCS-2,相等於 UTF-16。

由於JavaScript只能處理UCS-2編碼,造成所有字符在這門語言中都是2個字節,如果是4個字節的字符,會當作兩個雙字節的字符處理。JavaScript的String都受到這一點的影響,無法返回正確結果。

補充:
字符编码笔记:ASCII,Unicode和UTF-8
Unicode与JavaScript详解
字符编码 unicode 及其在javascript 中的使用

unicode 相關方法

unicode 表示法

javascript 可用 \uxxxx 表示字符,其中 'xxxx' 為碼點。


"\z" === "z"  // 跳脫字元
"\172" === "z" //  8進制轉義  、加 1~3位正整數,且整數不大於8
"\x7A" === "z" // \x 加 2 位16進制
"\u007A" === "z" // 、u 加 4 位16進制

超個單一字符需改用雙字節 表示


'\uD83D\uDE80'

es6 可用 \u{xxxx} 表示雙字節


"\u{1F680}" === "\uD83D\uDE80" // true

String.fromCharCode & String.fromCodePoint()

String.fromCharCode方法,用於從碼點返回對應字符,但是這個方法不能識別輔助平面的字符(編號大於0xFFFF)。

String.fromCharCode(0x20BB7);
String.fromCodePoint(42);       // "*"
String.fromCodePoint(65, 90);   // "AZ"
String.fromCodePoint(0x404);    // "\u0404"
String.fromCodePoint(0x2F804);  // "\uD87E\uDC04"
String.fromCodePoint(194564);   // "\uD87E\uDC04"
String.fromCodePoint(0x1D306, 0x61, 0x1D307) // "\uD834\uDF06a\uD834\uDF07"

charCodeAt() & codePointAt()

charCodeAt,用於回傳 unicode 的值,但是這個方法不能識別輔助平面的字符(編號大於0xFFFF)。


'A'.charCodeAt(0); // 65

'\uD800\uDC00'.codePointAt(0);

此方法可用來測試是基本或是輔助方面


function is32Bit(c) {
  return c.codePointAt(0) > 0xFFFF;
}

線上例子

unicode example

charAt() & at()

charAt方法,返回字符串給定位置的字符,但是這個方法不能識別輔助平面的字符(編號大於0xFFFF)。 但目前無實作…


'abc'.charAt(0) // "a"

normalize()

為了表示語調和重音符號,Unicode提供了兩種方法。一種是直接提供帶重音符號的字符,比如Ǒ(\u01D1)。另一種是提供合成符號(combining character) ,即原字符與重音符號的合成,兩個字符合成一個字符,比如O(\u004F)和ˇ(\u030C)合成Ǒ(\u004F\u030C)。


'\u01D1'.normalize() === '\u004F\u030C'.normalize()