JS字符串编码问题

在ES5之前,JS的字符串以16位的字符编码为基础。每个16位的序列都是一个码元,表示一个字符。但随着Unicode引入了扩展字符集,16位的字符编码便不再够用了(UTF-16 是变长的字符编码方式,有 16 位与 32 位两种情况。 JS 原先使用的则是固定 16 位(双字节)的字符编码方式)

UTF-16 码点

在UTF-16中位于0x0000-0xFFFF之间的码点,直接使用相同的16位码元表示,这个范围被称为多语言基本平面(BMP),超出该范围的码点将会落到扩展平面上。UTF-16引入代理对(使用两个16位的码元来表示单个码点)来解决这个问题 ;。

在ES5中,所有的字符串操作都是基于16位的码元,这表明在处理包含代理对UTF-16字符会出现意料外的结果。

vat text = "?"
console.log(text.length); // 2
console.log(/^.$/.test(text)); // false
console.log(text.charAt(0)); // ""
console.log(text.charAt(1)); // ""
console.log(text.charCodeAt(0)); // 55362
console.log(text.charCodeAt(1)); // 57271

这里"?"使用两个16位的码元表示,,所以在正则匹配单个字符的时候会返回false,charAt无法返回一个有效的字符,因为这里每16位码点都不是一个可打印的字符。
charCodeAt() 方法同样无法正确识别该字符,它只能返回每个码元的 16 位数字,但在 ES5中,这已经是对 text 变量所能获取到的最精确的值了。

codePointAt() 方法

ES6 为全面支持 UTF-16 而新增的方法之一是 codePointAt() ,它可以在给定字符串中按位置提取 Unicode 码点。该方法接受的是码元位置而非字符位置,并返回一个整数值,就像
下面的 console.log() 范例所展示的:

var text = "?a" ;
console.log(text.charCodeAt(0)); // 55362
console.log(text.charCodeAt(1)); // 57271
console.log(text.charCodeAt(2)); // 97
console.log(text.codePointAt(0)); // 134071
console.log(text.codePointAt(1)); // 57271
console.log(text.codePointAt(2)); // 97

codePointAt() 方法的返回值一般与 charCodeAt() 相同,除非操作对象并不是 BMP 字符。
text 字符串的第一个字符不是 BMP 字符,因此它占用了两个码元,意味着该字符串的length 属性是 3 而不是 2 。 charCodeAt() 方法只返回了位置 0 的第一个码元;而codePointAt() 返回的是完整的码点,即使它占用了多个码元。对于位置 1 (第一个字符的第二个码元)和位置 2 ( “a” 字符)来说,两个方法返回的值则是相同的。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值