在 ES6 之前,JS 字符串是基于 16 位的字符编码进行构建。每 16 位的序列是一个编码单元,代表一个字符。但是现在这 16 位满足不了字符数量的需求了。
UTF-16 码位
- Unicode 目的是给每一个字符提供唯一的数字标识,也称为码位(code point),从 0 开始。
- 用来表示字符的数字标识(码位),称为字符编码(character encode)。
现在字符有两种表示,完全依照 UTF-16 的表示方式:
- 16 位的字符,基本多文种平面(BMP),即只有一个编码单元
- 32 位的字符,也叫代理对,包含两个编码单元
ES5
所有的字符串操作基于 16 位的字符(即使此字符使用 32 位表示的)。
ES5 代码,IE11 控制台的运行结果:
var e = '😅';
=> undefined
e.length
=> 2
/^.$/.test(e)
=> false
e.charAt(0)
=> "���"
e.charAt(1)
=> "���"
e.char
=> undefined
e.charCodeAt(0)
=> 55357
e.charCodeAt(1)
=> 56837
长度属性是 2,而且第一个和第二个编码单元不是一个 BMP,显示乱码。
codePointAt 方法
ES6 新增方法。完全支持 UTF-16。
var e = '😅a';
=> undefined
e.length
=> 2
e.codePointAt(0)
=> 128517
e.codePointAt(1)
=> 56837
e.codePointAt(2)
=> 97
e.charCodeAt(0)
=> 55357
e.charCodeAt(1)
=> 56837
e.charCodeAt(2)
=> 97
到了 ES6,长度属性依然是 2。
但是,e.codePointAt(0)
返回的是一个完整的 UTF-16 编码,而非半个 16 位编码,是大于 0xFFFF
的。因此,可以借此判断字符占用的编码单元数量。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论。