ECMAScript 6:更好的 Unicode 支持

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

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

但隨着 Unicode 字符集 的不斷擴展,0x0000~0xFFFF 這個區間範圍,不足以表示全部字符了。這時再使用字符串的 length 屬性和 charAt() 方法就存在問題了。es6

碼點

  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)ui

  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 位編碼序列表示的。spa

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

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

從 charCode 到 codePoint

上面的例子裏,若是使用 codePointAt(),就不存在問題了。regexp

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

參考連接

(完)

相關文章
相關標籤/搜索