素材牛VIP会员
js Unicode码点问题
 陈***6  分类:Node.js  人气:1027  回帖:1  发布于6年前 收藏

es6中有:
'\u{1F680}' === '\uD83D\uDE80' //true
为什么呢?
或者应该问怎么由1F680推出 D83D DE80

讨论这个帖子(1)垃圾回帖将一律封号处理……

Lv6 码匠
坐***来 技术总监 6年前#1

曾经,人们天真的以为65536个就可以搞定世界上所有的符号,于是java里面就只用两个字节表示一个字符,js继承了这个东西。所以0x0041表示A 0x0042表示B,这种编码呢,叫做USC2

可是显然人们当年太天真了,65536个符号显然远远不够,后来人们发明了一种叫做UTF-16编码。这是编码基于在USC2里面,0xD8000xDFFF的编码是保留字符,这样当出现第一个字符的范围在其之间的时候,就可以认为它与后面的两个字节表示的是一个字符,曾经两个字节的字符在在utf-16叫做码点。一个字符可以有1-2个码点组成。utf-16是兼容usc2的于是javascript/java宣称,自己实际用的是utf-16

这种编码其实之用了0xD800-0xDFFF的一部分,两个码点组成的字符第一个码点要在0xD800-0xDBFF之间,即前六bit固定为1101 10。第二个码点要求在0xDC00-0xDFFF之间,即前六位固定为1101 11。这样每个码点可以空出10个bit,两个码点可以表示2^20个字符。(当然,JS并不检查这些码点的有效性,他只是把字符串当作一个16bit的无符号整形数组)

对于编码小于等于0xFFFF的就是两个字节,一个码点表示一个字符。对于大于0xFFFF的字符,先减去0x10000,然后转换为20bit的二进制数,然后分别填充如两个码点空出的10bit,这就是需要两个码点字符的保存方式。

ES6新语法规定,对于超出0xFFFF的编码可以直接用{}写出,如\u{xxxxx},对于\u{1F680}
0x1F680-0x10000=0xF680 = 0b0000 1111 0110 1000 0000
第一个码点是0b1101 10|00 0011 1101==0xD83D
第二个是0b1101 11|10 1000 000=0xDE80
更简洁的公式其实是((0x1F680-0x1000)>>10) + 0xD800((0x1F680-0x1000)|0x3FF) + 0xDC00
http://www.ecma-international...

 文明上网,理性发言!   😉 阿里云幸运券,戳我领取