Unicode基础知识与js

169 阅读5分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 N 天,点击查看活动详情

Unicode基础知识

码点

什么是码点

指与一个编码表中的某个字符对应的编码值。

在Unicode中,编码使用十六进制书写,并加上前缀U+

U+0041 对应字符A

码点的级别

码点分为17个代码级别。

第一个代码级别被称为基本的多语言级别,码点范围:U+0000 ~U+FFFF【也被称为基本平面】

剩余16个码点级别的范围: U+10000~U+10FFFF【也被称为增补平面】

代码单元

UTF-16编码采用不同长度的编码表示所有Unicode码点,在基本的多语言级别中,每个字符使用16位表示

UTF-16编码机制

使用16位作为一个代码单元。基本平面的码点使用一个代码单元。增补平面的码点使用2个代码单元。

但如何区分这一个代码单元是增补平面的一部分内容还是一个完整的基本平面的码点?

UTF-16使用基本平面在一个代码单元中未映射到的部分作为增补平面的代码单元的区域值。

而未映射的代码区域被称为替代区域。范围: U+D800~U+DFFF,2048个值。

这样这个范围之外的值为基本平面,之内的则这个代码单元所记录的值为增补平面的一部分。

pppp并无实际意义,不会影响代码单元表示的值。仅仅是根据这个定义的平面而已,和值没有关系。只是用这四个值去得知该代理对是哪个平面的。

为什么+U+D800和U+DC00

因为将整个增补平面

110110其实就是U+D800,

110111其实就是U+DC00

如何计算一个增补字符的两个代码单元的值

该标题下内容来自Unicode编码详解(四):UTF-16编码_hyongilfmmm的博客-CSDN博客_utf-16

①、将增补字符的码点值减去0x10000【因为0x10000为增补平面的第一个字符,此举是为了得到该码点为第几个增补平面的字符】,得到一个20位长的二进制数

②、将得到的20位长二进制数拆分为高10位比特和低10位比特

③、20位长的高10位比特加上0xD800得到第一个代理码点,即高代理码点

④、20位长的低10位比特加上0xDC00得到第二个代理码点,即低代理码点

⑤、将得到的高代理码点和低代理码点组合成“代理对”,便得到了增补字符的UTF-16编码

⑥、示例:求增补平面码点值为U+10437的UTF-16编码

将0x10437减去0x10000,得到0x00437,二进制为0000 0000 0100 0011 0111

将高10位,即0000 0000 01加上0xD800(二进制为1101 1000 0000 0000),得到高代理码点为:0xD801(二进制为1101 1000 0000 0001)

将低10位,即00 0011 0111加上0xDC00(二进制为1101 1100 0000 0000),得到低代理码点为:0xDC37(二进制为1101 1100 0011 0111)

将高代理码点和低代理码点组合成代理对得到UTF-16编码为0xD801 DC37

Unicode转义序列

作用

JavaScript定义了转义序列,从而可以仅使用ASCII字符来表示Unicode字符。

Unicode转义序列也可以出现在注释中,但因为注释会被忽略,所以注释中的转义序列会被作为ASCII字符处理。

也可以在标识符中用转义序列来表示一个Unicode字母。

书写格式

这些Unicode转义序列以\u开头,后跟 4 位十六进制数字【0-9、a-f 大小写都行】

Unicode转义序列在ES6中还可以\u开头,1~6位16进制数包含在花括号中表示。更好地支持了大于16位的Unicode码点。

Unicode可能导致的非语法错误

Unicode允许用多种编码方式表示同一个字符。所以可能出现2个字符,在编译器中呈现Unicode字符样式相同,但是其Unicode码点不同。

此时js会将这两个字符看作不同的字符。所以可能会发现以下情况,导致程序可读性极差,甚至可能因引用问题引发错误:

image.png

所以应该保证在程序中的Unicode字符经过归一化【一种字符形式只有一种与其对应的码点】

句末语

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 N 天,点击查看活动详情