ECMAScript 6:更好的 Unicode 支持

 2023-09-05 阅读 55 评论 0

摘要:在 ECMAScript 6 之前,JavaScript 对每个字符都是按照 16 位编码的(UTF-16)处理的。即默认每个字符在计算机底层都是由 16 个 0 和 1 的序列组成。 一个这样的 16 位序列称一个 编码单元(code unit)。 像字符串的 length 属性和 charAt()

在 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));    // 97console.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

参考链接

  • Better Unicode Support, from "Understanding ES6"

(完)

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/1/22.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息