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

参考连接

(完)

相关文章
相关标签/搜索