for...of 循环含有辅助平面字符的字符串,输出让我感到困惑

代码

let count = 0,
    s = "𠮷a";
for(let i of s){
    count ++;
    console.log(i);
}
for...of 输出:𠮷 a
console.log(count);//2
console.log(s.length);//3

疑惑的地方

1、字符串s的length为3,循环次数是2次;我用for循环测试,循环次数是3
次。
2、for...of在循环中做了那些事情导致循环次数少了一次?

阅读 3.2k
4 个回答

Javascript 采用 Unicode字符集,在 UTF-16 之前使用的是 UCS-2 编码,该编码方法使用2个字节表示字符(基本平面字符)。

UTF-16 编码发布后,UCS-2 被整合进 UTF-16,基本平面字符仍用2个字节,辅助平面字符使用4个字节表示。

因此,Javascript 的字符操作函数在处理4个字节的字符时,会当成两个双字节的字符处理,从而无法返回正确的结果。

s.slice(0, 1) // �
s.substr(0, 1) // �
s.charAt(0) // \uD842

"𠮷" 的 UTF-16 编码是4个字节的 0xD842 DFB7,而4个字节的字符不属于 UCS-2编码,javascript 会将其识别为U+D842U+DFB7 两个字符(在基本平面内,U+D800U+DFFF 是一个空段,不对应任何字符)

ES6 增强了 Unicode 支持,可以识别4字节的字符。除了for...of,还有以下方法

s.codePointAt(0).toString(16) // 20bb7
s.at(0) // 𠮷
String.fromCodePoint("0x20BB7") // 𠮷

length 属性返回字符串中字符编码单元的数量,所以也可能与实际的字符数量不相同。

想要返回字符串的正确长度,可以使用 Array.from(string).length

编码问题 for of es6新增的能正确识别

const a = s.charAt(0)
const b = s.charCodeAt(0)

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题