编码 & 字符集 & javascript
字符集
计算机只能存储二进制数据,为了存储字母、汉字、emoji 等,需要将其转换成二进制数据,这些转换就是根据字符集来做的。
ASCII 码就是一种字符集:
ASCII 码一共规定了 128 个字符的编码,比如空格 SPACE 是 32(二进制 00100000),大写的字母 A 是 65(二进制 01000001)。这 128 个符号(包括 32 个不能打印出来的控制符号),只占用了一个字节的后面 7 位,最前面的一位统一规定为 0。
Unicode 是一种更大更全的字符集:U+0041 表示英语的大写字母 A,U+4E25 表示汉字严,可以查询 unicode.org,或者专门的汉字对应表。
字符转换成二进制后,还需要解决两个问题
第一个问题是,如何才能区别 Unicode 和 ASCII ?计算机怎么知道三个字节表示一个符号,而不是分别表示三个符号呢?
第二个问题是,我们已经知道,英文字母只用一个字节表示就够了,如果 Unicode 统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是 0,这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍,这是无法接受的。
编码(解决上述两个问题)
UTF-8 就是在互联网上使用最广的一种 Unicode 的实现方式。其他实现方式还包括 UTF-16(字符用两个字节或四个字节表示)和 UTF-32(字符用四个字节表示)
UTF-8 的编码规则很简单,只有二条:
1)对于单字节的符号,字节的第一位设为 0,后面 7 位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的。
2)对于 n 字节的符号(n > 1),第一个字节的前 n 位都设为 1,第 n + 1 位设为 0,后面字节的前两位一律设为 10。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码。
UTF-8 示例
字符Næ⻬Unicode 编号(二进制)
01001110
11100110
00101110 11101100
Unicode 编号(十六进制)
4E
E6
2E EC
UTF-8 编码(二进制)
01001110
11000011 10100110
11100010 10111011 10101100
UTF-8 编码(十六进制)
4E
C3 A6
E2 BB AC
UFT-16 使用 2 个或者 4 个字节来存储。 对于 Unicode 编号范围在 0 ~ FFFF 之间的字符,UTF-16 使用两个字节存储,并且直接存储 Unicode 编号,不用进行编码转换,这跟 UTF-32 非常类似。
javascript
1 字节是 8 比特,表示成 2 进制需要 8 位,表示成 16 进制需要 2 位
js 中用 UTF-16 编码,一个字符编码成 1 个或 2 个 代码单元。每个代码单元占 2 个字节,需要 4 位 16 进制表示。
可以在 js 字符串里使用 unicode 如 '\u00E9'
js 中字符串的 length 属性是指代码单元的数量,不是指字符的数量
iterator 可以获取部分包含两个代码单元的字符串的正常长度(字符数而不是代码单元数),但不能正确获取包含 combining marks 的字符数,如"é",可以使用 normalize 方法转换后获取字符数
一个字符可以用不同的代码点组合,如"é"
对于 js 的===,即使打印出来的字符串一样,结果也可能是 false,需要使用 normalize 方法
参考
最后更新于
这有帮助吗?