# Unicode

# 介绍

Unicode 是目前绝大多数程序使用的字符编码,定义也很简单,用一个 码位(code point) 映射一个字符。码位值的范围是从 U+0000U+10FFFF,可以表示超过 110 万个字符

eg:

A 的码位 U+0041
a 的码位 U+0061
© 的码位 U+00A9
☃ 的码位 U+2603
💩 的码位 U+1F4A9

Unicode 最前面的 65536 个字符位,称为 基本多文种平面(BMP-—Basic Multilingual Plane),又简称为“零号平面”, plane 0), 它的码位范围是从 U+0000U+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+0000U+00FF 范围内的码位。

>> '\u0041\u0042\u0043'
   'ABC'
    
>> 'I \u2661 JavaScript!'
   'I ♡ JavaScript!

这些被称为 Unicode转义序列。它们由表示码位的 4 个十六进制数字组成。例如,\u2661 表示码位为 \U+2661 是一个心。这些转义序列可以用于 U+0000U+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+010000U+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;这俩个不同

# 参考

  1. JavaScript如何正确处理Unicode编码问题 (opens new window)
  2. javascript 转义工具 (opens new window)
陕ICP备20004732号-3