这是我参与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来遍历其值。
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'