这是我参与11月更文挑战的第13天,活动详情查看:2021最后一次更文挑战。
前言
ECMAScript 6.0 简称ES6 , 是 JavaScript 语言的新一代的标准,于在 2015 年 6 月发布,正式名称就是《ECMAScript 2015 标准》。一般情况,泛指, 5.1版以后的标准,涵盖了 ES2015、ES2016、ES2017、ES2018、ES2019、ES2020、ES2021 等等
我们一起来解开字符串�乱码之迷。
�乱码
我们用for遍历字符串, 会出现如下的乱码。
至于如何正确的遍历和取值,可以参见我的另一篇文章 字符串的遍历。
var text = "𢂘a𠮷人";
for(let i= 0; i< text.length; i++){
console.log(text[i]);
}
// �
// �
// a
// �
// �
// 人
Unicode简介
Unicode是一种字符集,Unicode是为整合全世界的所有语言文字而诞生的。没有规定应该如何存储, 所以才会有UTF-8, UTF-16, UTF-32等字符编码实现。
Unicode的编码空间从U+0000到U+10FFFF,共有1,112,064个码位可用来映射字符。
Unicode的编码空间可以划分为17个平面,每个平面包含216(65,536)个码位。17个平面的码位可表示为从U+xx0000到U+xxFFFF,其中xx表示十六进制值从0016到1016,共计17个平面。
第一个平面称为基本多语言平面(Basic Multilingual Plane, BMP),或称第零平面(Plane 0),其他平面称为辅助平面。
基本多语言平面内,从U+D800到U+DFFF之间的码位区段是永久保留不映射到Unicode字符。
UTF-16字符编码
Unicode字符集的编码值范围为0-0x10FFFF,大于等于0x10000的辅助平面区的编码值无法用2个字节来表示。
因为一个字节8个bit位,2个字节16个bit位,一位16进制,需要四个bit来表示, 最大能表示 0xFFFF。
UTF-16利用Unicode的代理区0xD800-0xDFFF区段的码位来对辅助平面的字符的码位进行编码。
在此之前,先提一下 码元:
码元(Code Unit,也称代码单元)是指一个已编码的文本中具有最短的比特组合的单元。对于UTF-8来说,码元是8比特长;对于UTF-16来说,码元是16比特长;对于UTF-32来说,码元是32比特长。
UTF-16编码过程:
- 码位减去
0x10000,得到的值的范围为20比特长的0...0xFFFFF,不足的话,前面补0喽。 - 高位的10比特的值加上
0xD800得到第一个码元 - 低位的10比特的值加上
0xDC00得到第二个码元
我们以𢂘为例:
其码位为 0x22098
"𢂘".codePointAt(0).toString(16) // 22098
- 码点减去
0x10000,0x22098-0x10000=0x12098=0001001000 0010011000 - 分割上10位和下10位, 上:
0001001000, 下:0010011000 - 上10位 +
0xD800,0001001000+0xD800=0x48+0xD800=0xD848 - 下10位 +
0xDC00,0010011000+0xDC00=0x98+0xDC00=0xDC98
我们怎么验证结果呢?
var ch = "𢂘";
ch.charAt(0) // '\uD848'
ch.charAt(1) // '\uDC98
没错,完全一致。
U+D800到U+DFFF 区间没有字符是没法打印的,故打印�。
接下来
接下来我们推导,为什么大于 0xFFFF的字符,打印一定是�。
小结
今天你收获了吗?