Unicode为世界上所有的文字系统的每一个字符单位分配了一个唯一的整数,称为代码点,范围为:0~1114111;
ASCII将每一索引映射为唯一的二进制表示,但Unicode允许多个不同二进制编码的代码点;
不同的编码在要求存储的字符串数量和操作速度之间进行平衡,由此产生如UTF-8,UTF-16,UTF-32;
历史发展:
- 早期由于错误地估算了代码点的容量范围,认为Unicode最多只需要2^16个代码点,而产生了USC-2,为16位编码的原始标准;
- USC-2是由独立的16位代码单元组成的,每个代码单元对应一个单独的Unicode代码点;
- 这种编码的好处在于索引字符串是一种代价小,固定时间的操作;获取某个字符串的第N个代码点只要选取数组的第N个16位元素;(0X0000)
- 结果是许多平台如Java,JavaScript等都采用16位编码的字符串;
- 随后Unicode扩大范围之后,新增加了17个大小为2^16的代码点范围;第一个子范围称为基本多文种平面,其他16个范围称为辅助平面;
- 之后UTF16取代USC-2,其采用代理对表示附加的代码点;一对16位的代码单元共同编码一个等于或大于2^16的代码点;
- 这导致了:
- 代码单元的索引与代码点的索引不同;
- UTF-16是一种可变长度的编码;
- 长度为N的字符串内存大小变化基于该字符串特定的代码点;
- 查找N个代码点不再是固定时间;
Javascript的影响:
- 当Unicode扩大范围时,Javascript已经采用16位的字符串元素,字符串的属性和方法都是基于代码单元层级,而不是代码点层级;
- 所以当字符串包含辅助平面中的代码点时,Javascritp将每个代码点表示为两个元素;即一个Javascirp字符串的元素是一个16位的代码单元;
- 考虑到字符串的属性和方法,字符串表现得像UTF-16的代码单元序列;所以在对字符串计数的时候,如包含辅助平面,长度可能会有不同;
- 类似的在正则表达式也是工作与代码单元层级;其单子模式匹配('.')一个单一的代码单元;所以遇到辅助平面字符时可能需要('..')才能匹配;
所以Javascript在处理特殊的Unicode编码的字符串时要注意;