Unicode
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
- 阮一峰《ECMAScript 6 入门》http://es6.ruanyifeng.com/#docs/string
- 阮一峰《字符编码笔记:ASCII,Unicode和UTF-8》http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html
- 阮一峰《Unicode与JavaScript详解》 http://www.ruanyifeng.com/blog/2014/12/unicode.html
blog comments powered by Disqus