# Unicode
# 介绍
Unicode 是目前绝大多数程序使用的字符编码,定义也很简单,用一个 码位(code point) 映射一个字符。码位值的范围是从 U+0000
到 U+10FFFF
,可以表示超过 110 万个字符
eg:
A 的码位 U+0041
a 的码位 U+0061
© 的码位 U+00A9
☃ 的码位 U+2603
💩 的码位 U+1F4A9
Unicode 最前面的 65536 个字符位,称为 基本多文种平面
(BMP-—Basic Multilingual Plane),又简称为“零号平面”, plane 0), 它的码位范围是从 U+0000
到 U+FFFF
。最常见的字符都放在这个平面上,这是 Unicode 最先定义和公布的一个平面。
剩下的字符都放在 辅助平面(Supplementary Plane) 或者 星形平面(astral planes) ,码位范围从 U+010000
一直到 U+10FFFF
,共 16 个辅助平面
辅助平面内的码位很容易识别:如果需要超过 4 个十六进制数字来表示码位,那么它就是一个辅助平面内的码
# 转义序列
在谷歌控制台输入如下:
>> '\x41\x42\x43'
'ABC'
>> '\x61\x62\x63'
'abc'
十六进制转义序列。它们由引用匹配码位的两个十六进制数字组成。例如,\x41
码位为 U+0041
表示大写字母A
。这些转义序列可用于 U+0000
到 U+00FF
范围内的码位。
>> '\u0041\u0042\u0043'
'ABC'
>> 'I \u2661 JavaScript!'
'I ♡ JavaScript!
这些被称为 Unicode转义序列。它们由表示码位的 4 个十六进制数字组成。例如,\u2661
表示码位为 \U+2661
是一个心。这些转义序列可以用于 U+0000
到 U+FFFF
范围内的码位,即整个基本平面。
但是其他的所有辅助平面呢? 我们需要 4 个以上的十六进制数字来表示它们的码位,那么如何转义它们呢?
在 ECMAScript 6中,这很简单,因为它引入了一种新的转义序列: Unicode 码位转义。例如:
>> '\u{41}\u{42}\u{43}'
'ABC'
>> '\u{1F4A9}'
'💩' // U+1F4A9 PILE OF POO
在大括号之间可以使用最多 6 个十六进制数字,这足以表示所有 Unicode 码位。因此,通过使用这种类型的转义序列,可以基于其代码位轻松转义任何 Unicode 码位。
为了向后兼容 ECMAScript 5 和更旧的环境,不幸的解决方案是使用代理对
:
>> '\uD83D\uDCA9'
'💩' // U+1F4A9 PILE OF POO
在这种情况下,每个转义表示代理项
一半的码位。两个代理项
就组成一个辅助码位
注意,代理项对码位 与 原始码位 不同。有公式可以根据给定的辅助码位来计算代理项对码位,反之亦然——根据代理对计算原始辅助代码位
使用代理对,所有辅助平面中的码位(即从 U+010000
到 U+10FFFF
)都可以表示,但是使用一个转义来表示基本平面的码位,以及使用两个转义来表示辅助平面中的码位,整个概念是令人困惑的,并且会产生许多恼人的后果。
# javascript如何处理unicode编码
# 在js中计算字符的长度
首先想到可能是使用 length 属性
>> 'A'.length // 码位: U+0041 表示 A
1
>> 'A' == '\u0041'
true
>> 'B'.length // 码位: U+0042 表示 B
1
>> 'B' == '\u0042'
true
在这些例子中,字符串的 length 属性恰好反映了字符的个数。这是有道理的:如果我们使用转义序列来表示字符,很明显,我们只需要对每个字符进行一次转义。但情况并非总是如此!这里有一个稍微不同的例子:
>> '𝐀'.length // 码位: U+1D400 表示 Math Bold 字体大写 A
2
>> '𝐀' == '\uD835\uDC00'
true
>> '𝐁'.length // 码位: U+1D401 表示 Math Bold 字体大写 B
2
>> '𝐁' == '\uD835\uDC01'
true
>> '💩'.length // U+1F4A9 PILE OF POO
2
>> '💩' == '\uD83D\uDCA9'
true
在内部,JavaScript 将辅助平面内的字符表示为代理对
,并将单独的代理对部分开为单独的字符
。
如果仅使用 ECMAScript 5 兼容转义序列来表示字符,将看到每个辅助平面内的字符都需要两个转义
如何准确地计算 JavaScript 字符串中的字符个数?
诀窍就是如何正确地解析代理对,并且只将每对代理对作为一个字符计数,具体的方法有多种,参考链接的文章
# Unicode字符和html实体字符的关系
普通空格在utf-8里的编码是\u0020
,而
的编码是 \u00A0
;这俩个不同