字符串的遍历

812 阅读1分钟

这是我参与11月更文挑战的第12天,活动详情查看:2021最后一次更文挑战

前言

ECMAScript 6.0 简称ES6 , 是 JavaScript 语言的新一代的标准,于在 2015 年 6 月发布,正式名称就是《ECMAScript 2015 标准》。一般情况,泛指, 5.1版以后的标准,涵盖了 ES2015、ES2016、ES2017、ES2018、ES2019、ES2020、ES2021 等等

我们一起来学习增强的字符串吧。

字符串的遍历的问题

大家都知道, 字符串可以使用索引值来获取对应的字符。

var text = "abc";
for(var i = 0; i < text.length; i++){
    console.log(text[i]);
}
// a
// b
// c

咋眼一看没啥问题,但是别忘记了, js是采用utf-16编码来保存字符的, 码点大于0xffff的字符是占四个字节的,对应的length属性是2。

"𢂘".length //2

我们再试试使用for循环遍历

var text = "𢂘";
for(var i = 0; i < text.length; i++){
    console.log(text[i]);
}
// �
// �

纳尼,这是什么玩意儿。 参考 unicode 对照表 U+D800 到 U+DFFF都是不可打印的,显示都是�。

"𢂘".charAt(0) // '\uD848'
"𢂘".charAt(1) // '\uDC98'

至于 码点为0x22098的charAt为什么是'\uD848''\uDC98'我们单独的文章再讨论。

ES6字符串遍历

好在,ES6考虑到了这个问题, 其原型上实现了Symbol.iterator,使得其可以使用for of来遍历其值。

image.png

var text = "𢂘";
for(let v of text){
    console.log(v);
}
// "𢂘"

可以看到,这个能得到其准确的值,而不是乱码,哈哈,直言666啊。

不使用for of遍历

我们知道如果码点大于0xffff的下一个索引值的值,是不可用的。我们直接跳过就好。

var text = "𢂘a𠮷人";
var code;
var skip;
for (var i = 0; i < text.length; i++) {
  if (skip) {
    skip = false;
    continue;
  }
  code = text.codePointAt(i);
  console.log(String.fromCodePoint(+`0x${code.toString(16)}`));
  if (code > 0xffff) {
    skip = true;
  }
}
// 𢂘
// a
// 𠮷
// 人

这样看起来可不行,我们封装一下。

封装的话,需要额外处理一下index的值。

function strforEach(str, callback) {
  var code;
  var skip;
  var index = 0;
  for (var i = 0; i < str.length; i++) {
    if (skip) {
      skip = false;
      continue;
    }
    code = str.codePointAt(i);
    callback(String.fromCodePoint(+`0x${code.toString(16)}`), index, str);
    index++

    if (code > 0xffff) {
      skip = true;
    }
  }
}

测试一下结果:

var text = "𢂘a𠮷人";
strforEach(text, function (ch, index, str) {
  console.log(ch, index, str);
})
// 𢂘 0 𢂘a𠮷人
// a 1 𢂘a𠮷人
// 𠮷 2 𢂘a𠮷人
// 人 3 𢂘a𠮷人

当然,你遍历时候去更改字符串本身,那就是一件很危险的事情啦。

问题环节

能使用Object.values()来获取字符串的全部值吗?

Object.values("𢂘a𠮷人")
(6) ['\uD848', '\uDC98', 'a', '\uD842', '\uDFB7', '人']

答案是显然不能。

能使用拓展运算获取全部的值吗

当然是可以,因为字符串实现了Symbol.iterator

[..."𢂘a𠮷人"]
(4) ['𢂘', 'a', '𠮷', '人']

这个方便。

小结

综上,最简单的方式,当然是拓展运算符了。 今天你收获了吗?

接下来

接下来我们一起来揭开那个神奇的 ��

"𢂘".charAt(0) // '\uD848' 
"𢂘".charAt(1) // '\uDC98'