美文网首页
关于JavaScript编码你应该知道的

关于JavaScript编码你应该知道的

作者: tangyefei | 来源:发表于2019-10-26 22:19 被阅读0次

1. 字符集和编码的关系

字符集是字符的集合,编码则是字符集中的字符要如何存储的规则。

image.png

如上图,当字符集和编码一一对应时,可能不用特意去区分;当字符集和编码一对多时,要指明编码方式就必须用准确的名称。

2. Unicode的码点

Unicode将全世界所有的符号都包含在其中,它的符号分别定义在不同的17个平面中,每个平面包含65536个(2^16)字符。

第一个平面称为基本平面,剩下的平面成为辅助平面。


image.png

参考上图的编号规则,可以看到

  • Unicode的码点用十六进制表示,长度在4-6位之间,少于4位实际有效前面会用0填充
  • 4位十六进制等同于2字节:16^4 = (2^4)^4 =2^16=16bit

3. Unicode的编码方式

Unicode的编码方式有多种:

  • UTC-32用4个字节表示一个字符,缺点是浪费空间
  • UTC-8用1-4个字节表示一个字符,是常见的网页编码
  • UTC-16用2或4个字节表示一个字符,结合定长和变长编码方法的特点

因为JavaScipt的编码UCS-2会跟UTC-16有一定的关系,这里作为拓展介绍一下UTC-16是如何确定一个字符是用2个字节还是4个字节表示。

(1)基本平面的字符用2字节表示(即4位16进制),直接转成对应的十六进制即为UTF-16的表示;

(2)辅助平面的字符码点范围在 U+010000~U+10FFFF之间,要把码点拆分到4个字节中就会面临一个问题,你怎么判定你拆分出来的2子节的单元是独立的还是和后续单元一起。

在基本平面内,有一个区间是不设置具体含义的,这个区间的大小为 2(2^10), 我们把辅助平面的字符一半放在前2个字节,一半放在后2个字节,各自大小为2^10长度,那么得到的总长度就是 2^20 = (2^16)16 = 辅助平面大小*16

UTF-16编码规则

看到如果有编码是在 D800-DFFF之间,基本就可以判定是辅助平面的字符。

4. JavaScript的编码UCS-2

Javascript使用的编码非上面的任何一种,而是用的UCS-2的编码,它采用两个字节存储一个字符。

UCS团队早期和Unicode团队一样,都是为了建立一个涵盖所有字符的字符集。UCS-2是支持UCS字符集的编码方式。

JavaScript语言采用了UCS-2作为自己的编码方式,那时候只有一个基本平面,2个字节就够用了。

而后才有了UCS和Unicode两家成员决定合并保留Unicode一个字符集,进一步发展出UTC-16的故事。

UTC-16明确宣布是UCS-2的超级,即基本平面跟UCS-2一样,辅助平面用于4个字节的表示。

因为JavaScript只能处理UCS-2编码,4个字节的字符,会当做两个双字节字符来处理,因此所有字符串的函数都无法正确返回结果。

5. 编码相关实用方法

5.1 字符和字节的关系

Javascript使用UCS-2编码,一个字符用两个字节表示:1字符 = 2字节

5.2 字符串的长度

基本平面的字符长度为1,辅助平面的字符长度为2,因此视觉长度为n的字符串,实际使用 length 属性获得的长度可能在 n-2n之间。

5.3 字符编码的查看

可以使用 String.prototype.chartCodeAt(index)toString(16)来查看字符的十进制编码:

'a'.charCodeAt(0).toString(16) // 61

5.4 四字节字符的遍历

一个四个字节表示的字符,可以使用数组下标 或 for...in 循环遍历到两个双字节,每一个只是字符的一部分,输出是无正常展示的;而ES6提供的 for...of 可以自动识别四字节的编码。

var s = '𝌆';
for(var i in s){
  console.log(s[i])
  //�
  //�
}

for(var i of s){
  console.log(s[i])
  //𝌆
}

5.5 码点表示法

如下的表达式是成立的,其中第三是ES6为了识别4字节字符所处的修复,加上{}才能正常识别


'\u0061' === 'a'

// 使用两个双字节表示一个辅助平面字符
'\ud834\udf06' === '𝌆'

//ES6新增的码点表示法
'\u{1d306}' === '𝌆'

5.6 其他方法

  • String.fromCodePoint():从Unicode码点返回对应字符,参数为十进制十六进制皆可
  • String.prototype.codePointAt():从字符返回对应的码点,'𝌆'.codePointAt(0) 的输出即为 1d306
  • String.prototype.at():返回字符串给定位置的字符,自己浏览器尝试了一把暂时不支持
  • 正则表达:ES6提供了u修饰符,对正则表达式添加4字节码点的支持。
/^.$/u.test('𝌆') // true
/^.$/.test('𝌆') // false

6. 参考

相关文章

网友评论

      本文标题:关于JavaScript编码你应该知道的

      本文链接:https://www.haomeiwen.com/subject/ynguvctx.html