我喜欢略过不相关的概念,直奔主题,当过教师的习惯。
人的思维总是有历史局限性的,早期人们在C语言中用char
命名256个ASCII码,却没想到全世界的文字数量远不止这么多。
后来人们在JavaScript语言里用char
命名65536个Unicode字符,却没想到现在的数量又远远超出,比如各种生僻字、Emoji等。
所以JavaScript只能增加一个新名词code point
表示现代意义的字符,可以超过65536,而原来不能超过65536的命名char
为了兼容性只能保留。
str.length
、str[i]
、str.charCodeAt(i)
、String.fromCharCode(...)
等都是老方式,如果字符超过65536,会被拆成两个char
,如果你打印其中的单个char
就有就可能“乱码”。
而...str
、c of str
、str.codePointAt(i)
、String.fromCodePoint(...)
等是新方式,超过65536的字符不会被拆分。
比如:
let str = '𠮷😍';
let arr = [];
for (let i = 0; i < str.length; i++) {
let c = str[i];
console.log(c);
arr[i] = c.charCodeAt(); // 或者str.charCodeAt(i);
}
console.log(arr);
console.log(String.fromCharCode(...arr));
for (let c of str) {
console.log(c);
}
arr = [...str].map(c => c.codePointAt());
console.log(arr);
console.log(String.fromCodePoint(...arr));
输出:
�
�
�
�
[ 55362, 57271, 55357, 56845 ]
𠮷😍
𠮷
😍
[ 134071, 128525 ]
𠮷😍
可以看到,老方式下,两个超出65536的字符被拆成了四个char
,打印出来都是乱码,不过合并之后完好如初。而新方式的拆分、合并都没有任何问题。