ECMAScript 6:更好的 Unicode 支援

zhangbao90s發表於2019-01-24

在 ECMAScript 6 之前,JavaScript 對每個字元都是按照 16 位編碼的(UTF-16)處理的。即預設每個字元在計算機底層都是由 16 個 0 和 1 的序列組成。 一個這樣的 16 位序列稱一個 編碼單元(code unit)

像字串的 length 屬性和 charAt() 方法都是基於 16 位編碼單元進行處理的。

但隨著 Unicode 字符集 的不斷擴充套件,0x0000~0xFFFF 這個區間範圍,不足以表示所有字元了。這時再使用字串的 length 屬性和 charAt() 方法就存在問題了。

碼點

  1. 碼點(Code Points)就是字元編碼,用一個數字表示一個字元。
  2. 碼點既能表示 0x0000~0xFFFF 範圍的字元,也能表示 > 0xFFFF 範圍之外的字元。
  3. 碼點在計算機底層由 1 個或 2 個編碼單元組成。

BMP

0x0000~0xFFFF 區間範圍,稱為 Basic Multilingual Plane (BMP)。在 BMP 中(包括),一個字元唯一對應一個編碼單元(一個 16 位二進位制序列)。

BMP 之外的區間稱為 supplementary planes。在 supplementary planes 中的每個字元,由 2 個編碼單元組成,稱 代理對(surrogate pairs)

  1. 0x0000~0xFFFF 區間範圍,一個碼點等於一個編碼單元。
  2. > 0xFFFF 區間範圍,一個碼點等於兩個編碼單元。

老方法的問題

在 ECMAScript 5 中,每個字元都被看做,由一個編碼單元組成。那麼,在處理 supplementary planes 中的字元時,就有問題了。

var text = "?";

console.log(text.length);           // 2
console.log(/^.$/.test(text));      // false
console.log(text.charAt(0));        // ""
console.log(text.charAt(1));        // ""
console.log(text.charCodeAt(0));    // 55362
console.log(text.charCodeAt(1));    // 57271
複製程式碼

"?" 在計算機底層由兩個編碼單元組成,也就是由兩個 16 位編碼序列組成。而在 .length 屬性、charAt() 方法和 charCodeAt() 方法的世界觀裡,每個字元都是用一個 16 位編碼序列表示的。

所以,.length 屬性值是 2;charAt(0)charAt(1) 其實取的是 "?" 這個字第一個編碼單元和第二個編碼單元所表示的字元;charCodeAt(0) 更不能取到正確的字元了。

本質上,charAtcharCodeAt 後面的數字是表示編碼單元的索引值。

從 charCode 到 codePoint

上面的例子裡,如果使用 codePointAt(),就不存在問題了。

var text = "?a";

console.log(text.charCodeAt(0));    // 55362
console.log(text.charCodeAt(1));    // 57271
console.log(text.charCodeAt(2));    // 97

console.log(text.codePointAt(0));   // 134071
console.log(text.codePointAt(1));   // 57271
console.log(text.codePointAt(2));   // 97
複製程式碼

> 0xFFFF 區間範圍,字元編碼值(char code) 不再有效,碼點依舊有效。所以,我們要:

  • String.fromCharCode 遷移到 String.fromCodePoint
  • string.charCodeAt 遷移到 string.codePointAt

工具方法:is32Bit

我們可以寫一個工具方法,判斷一個字元是不是 BMP 之外的字元。

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

console.log(is32Bit("?"));         // true
console.log(is32Bit("a"));          // false
複製程式碼

擴充套件連線

  1. Universal Character Set characters, from wikipedia.org
  2. Character Code Charts, from unicode.org

參考連結

(完)

相關文章