Sat, 07 May 2016 10:41:42 +0000

Unicode

Unicode 是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案

Unicode

ASCII 码

ASCII(American Standard Code for Information Interchange,美国标准信息交换代码)。

二进制(bit)有 0、1 两种状态。八个是一个字节(byte),有 256 种状态。

常用对照表

UTF

UTF,是 Unicode Transformation Format 的缩写,意为 Unicode 转换格式。

UTF-8(变长的编码方式)

UTF-8(8-bit Unicode Transformation Format)是一种针对 Unicode 的可变长度字符编码。

UTF-8的编码规则很简单,只有二条:

  • 1)对于单字节的符号,字节的第一位设为 0,后面 7 位为这个符号的 unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的。
  • 2)对于 n 字节的符号(n>1),第一个字节的前 n 位都设为 1,第 n+1 位设为 0,后面字节的前两位一律设为 10。剩下的没有提及的二进制位,全部为这个符号的 unicode 码。

UTF-8 编码规则:

Unicode 符号范围 | UTF-8 编码方式
(十六进制) | (二进制)
--------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx | 7
0000 0080-0000 07FF | 110xxxxx 10xxxxxx | 11
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx | 16 0x10000
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx | 21 0x200000

JavaScript 下的操作:

'严'.charCodeAt(0).toString(16) // "4e25" 100111000100101
encodeURI('严') // "%E4%B8%A5" 111001001011100010100101
01234567 01234567 01234567 01234567 01234567
11100100 10111000 10100101 1001110 00100101

即,unicode 不够 16 位的,前面补 0。因为这个「严」在 FFFF 这个范围内,选第三个,1110xxxx 10xxxxxx 10xxxxxx 可以用来接受 16 位的值。

| 1110 0100 | 10 1110 00 | 10 100101 |

Others

UTF-16(字符用两个字节或四个字节表示)和UTF-32(字符用四个字节表示)。

ES6

说明:

  • ES6 提供了 codePointAt、String.fromCodePoint 方法。
  • 可以用 for…of 正确打印。

ES6 Unicode 详细介绍:

JavaScript 允许采用 \uxxxx 形式表示一个字符,其中“xxxx”表示字符的码点。

"\uD842\uDFB7"
// "𠮷"

"\u20BB7"
// " 7"

但是,这种表示法只限于 \u0000——\uFFFF 之间的字符,超出的要用双字节。

ES6 可以

"\u{20BB7}"
// "𠮷"

"\u{41}\u{42}\u{43}"
// "ABC"

let hello = 123;
hell\u{6F} // 123

'\u{1F680}' === '\uD83D\uDE80'
// true

JavaScript 共有 6 种方法可以表示一个字符

'\z' === 'z'  // true
'\172' === 'z' // true
'\x7A' === 'z' // true
'\u007A' === 'z' // true
'\u{7A}' === 'z' // true

汉字“𠮷”的码点是0x20BB7,UTF-16编码为0xD842 0xDFB7(十进制为55362 57271) ES6提供了codePointAt方法,能够正确处理4个字节储存的字符,返回一个字符的码点。

var s = '𠮷a';

s.codePointAt(0) // 134071
s.codePointAt(1) // 57271

s.charCodeAt(2) // 97

JavaScript将“𠮷a”视为三个字符,codePointAt方法在第一个字符上,正确地识别了“𠮷”,返回了它的十进制码点134071(即十六进制的20BB7)。在第二个字符(即“𠮷”的后两个字节)和第三个字符“a”上,codePointAt方法的结果与charCodeAt方法相同。codePointAt参数不正确,这时可以用for...of循环。

var s = '𠮷a';
for (let ch of s) {
  console.log('unicode', ch.codePointAt(0).toString(16));
  console.log('string', ch);
}
// unicode 20bb7
// string 𠮷
// unicode 61
// string a

ES5提供String.fromCharCode不能识别 32 位的 UTF-16 字符。溢出,最高位被舍弃了。

String.fromCharCode(0x20BB7)
// "ஷ"

ES6提供了String.fromCodePoint方法,可以识别 0xFFFF 的字符。正好与codePointAt方法相反。

String.fromCodePoint(0x20BB7)
// "𠮷"
String.fromCodePoint(0x78, 0x1f680, 0x79) === 'x\uD83D\uDE80y'
// true

References



blog comments powered by Disqus