为什么'\u{1F680}'==='\uD83D\uDE80'
首先需要了解JS
代码里面的unicode
编码字符的语法是:\uXXXX
.这种表示法只能记录码点在\u0000~\uFFFF
之间(即0~65535
)的字符,超出这个范围的字符,必须用两个双字节的形式表示.
对于大于0xFFFF
(即65535
0x
即16进制)的字符,先减去0x10000
(即65536
),然后转换为20bit
的二进制数,然后分别填充两个码点空出的10bit
,这就是需要两个码点字符的保存方式。
码点一: 0b110110
(0b
即二进制)
码点二: 0b110111
但是为什么是这两个码点呢?这与Unicode
编码的设计者的设计有关.Unicode
编码0xD800-0xDFFF
,共2048个码位,是一个被称作代理区(Surrogate)的特殊区域.代理区的目的用两个UTF-16字符表示0~0xFFFF
(即0~65535
)以外的字符。所有大于0xFFFF
的码需要使用代理区的码点。
目前Unicode最大的码位是0x10FFFF
(即1114111
)
0x010000-0x10FFFF
,需要使用2个代理码元表示,第一个码元为0xD800-0xDBFF
(高位)范围是:1101 10
00 0000 0000到1101 10
11 1111 1111,第二个码元为0xDC00-0xDFFF
(低位)范围是:1101 11
00 0000 0000到1101 11
11 1111 1111.
十进制 | Unicode编码 | 说明 | 说明 |
---|---|---|---|
55296-56191 | 0xD800-0xDB7F(896个) | High Surrogates | 高位替代 |
56192-56319 | 0xDB80-0xDBFF(128个) | High Private Use Surrogates | 高位专用替代 |
56320-57343 | 0xDC00-0xDFFF(1024个) | Low Surrogates | 低位替代 |
接下来我们把Unicode编码>65535
的记为U,我们先计算U'=U-0x10000
,然后将U'
写成二进制形式:yyyy yyyy yyxx xxxx xxxx
,那么U的UTF-16编码(二进制)就是:110110yyyyyyyyyy110111xxxxxxxxxx
.
了解前边两个码点后,那么 0x1F680
如果用两个双字节表示呢
先计算
0x1F680-0x10000
结果为0xF680
(0x1F680-0x10000).toString(16)
0xF680
转化为2进制结果为0b1111 0110 1000 0000
0xf680.toString(2)
将上一步结果补全为20位的二进制数
0b0000 1111 0110 1000 0000
(前面加4个0)- 填充两个码点空出的
10bit
,第一个码点填充为0b1101 1000 0011 1101
第二个码点填充为0b1101 1110 1000 0000
- 将两个填充后的码点转化为十六进制即为
0xD83D
和0xDE80
.
即'\u{1F680}'==='\uD83D\uDE80'