JavaScript 字符集和编码
字符集是字符的集合,编码则是字符集中的字符要如何存储的规则。
当字符集和编码一一对应时,可能不用特意去区分;当字符集和编码一对多时,要指明编码方式就必须用准确的名称。
Unicode 将全世界所有的符号都包含在其中。它的符号分区定义在不同的1个平面中,每个平面包含 65536 个(216)字符。
第一个平面称为基本平面,剩下的平面成为辅助平面。
对应的可以看到 Unicode 的码点用十六进制表示,长度在 4-6 位(少于4位实际有效前面会用0填充)之间。
Unicode 的编码方式有多种:
- UTC-32用4个字节表示一个字符
- UTC-8用1-4个字节表示一个字符
- UTC-16用2或4个字节表示一个字符
JavaScript 使用的编码非上面的任何一种,而是用的 UCS-2 的编码,UCS-2 编码采用两个字节存储一个字符。
UCS 早期 Unicode 一样,都是为了建立一个涵盖所有字符的字符集。UCS-2 是支持 UCS 的编码方式。
JavaScript 语言采用了 UCS-2 作为自己的编码方式,而后又有了 UCS、Unicode 两家成员决定合并保留 Unicode 一个字符集,进一步发展出 UTC-16 的故事。
UTC-16 明确宣布是 UCS-2 的超级,即基本平面跟 UCS-2 一样,辅助平面用于 4 个字节的表示。
字符串的字节数
因为 JavaScript 使用 UCS-2 编码,一个字符用两个字节表示,因此字节数的数量的表达式为:字节数量 = 字符串长度 * 2。
比较特殊的,一个包含四个字节的字符,其长度为 2,因此上述公式仍适用。
字符编码的查看
可以使用 String.prototype.chartCodeAt(index)
加 toString(16)
来查看字符的十进制编码:
'a'.charCodeAt(0).toString(16) // 61
四字节字符的遍历
一个四个字节表示的字符,可以使用数组下标 或 for...in
循环遍历到两个4位十六进制,每一个只是字符的一部分,输出是无正常展示的;而 ES6 提供的 for...of
可以自动识别四字节的编码。
var s = '';
for(var i in s){
console.log(s[i])
//?
//?
}
for(var i of s){
console.log(s[i])
//
}
码点表示法
如下的表达式是成立的,其中第三是 ES6 为了识别 4 字节字符所处的修复,加上 {}
才能正常识别
'\u0061' === 'a'
'\ud834\udf06' === ''
'\u{1d306}' === ''
其他方法
''.codePointAt(0)
的输出即为 1d306
- String.fromCodePoint():从 Unicode 码点返回对应字符,参数为十进制十六进制皆可
- String.prototype.codePointAt():从字符返回对应的码点
- String.prototype.at():返回字符串给定位置的字符,自己尝试似乎暂时不支持
正则表达
ES6 提供了 u 修饰符,对正则表达式添加 4 字节码点的支持。
/^.$/u.test('') // true
/^.$/.test('') // false
一道笔试题
要使用 utf-8 来存储 你好,Señorita 需要用到多少个字节?
知识:要知道每个字符用 utf-8 编码占用的长度不一致,需要找到参考依据
思路:将字符串通过 charCodeAt(i 0->11).toString(16) 来得到 16 进制的表示:
var s = "你好,**Señorita";
for(var i = 0; i < s.length; i++) {console.log(s.charCodeAt(i).toString(16));}
// 4f60 3
// 597d 3
// 2c 1
// 53 1
// 65 1
// f1 2
// 6f 1
// 72 1
// 69 1
// 74 1
// 61 1
total 16
参考资料
- 字符编码笔记:ASCII,Unicode 和 UTF-8 by 阮一峰
- Unicode与JavaScript详解 by 阮一峰
- 阮一峰老师文章的常识性错误之 Unicode 与 UTF-8 by 刘志军
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: JavaScript 中的类型转化
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论