码元和码点
1.介绍码元和码点
在计算机中存储字符不是存储一个真正的字符,而是存储这个字符对应的ascll编码值。在js中,一个字符占16位空间也就是2个字节,而这个空间就称之为码元,一个码元的存储空间是0-2的16次方,也就是65535,而在现实生活中我们的文字绝不只这点于是想要存储一个字符所占空间大于65535的话,js就会开两个空间给这个字符,而这个字符所占的全部空间就称之为码点。
2.码元码点的实际用途
在js中,我们通过字符串的length属性实际上是在访问这个字符串所占的码元。
const string = "😭🦐"
console.log(string.length); // 4
所以在开发中我们遇到表情这种占两个码元的字符时,处理起来会有点问题,如:
const string = "😭🦐"
console.log(string.slice(0,1)) // 输出乱码
因为slice方法实际上也是根据字符的码元进行截取,而字符串里的一个字符是占两个码元的所以当我们想截取第一个字符的时候只截取到了他第一个码元,还有一个码元没有截取到,所以会导致乱码。
解决办法就是在字符串原型上添加几个专门处理表情等字符的方法。
一,方法一
在字符串原型上添加pointLength方法,用于获取字符串的码点数量
String.prototype.pointLength = function () {
let len = 0;
for (let i = 0; i < this.length; ) {
len++;
const t = this.codePointAt(i);
i += t > 0xffff ? 2 : 1;
}
return len;
};
二,方法二
在字符串原型上添加pointAt方法,用于获取字符串中指定码点索引的字符。
String.prototype.pointAt = function (index) {
let currentIndex = 0;
for (let i = 0; i < this.length; ) {
if (currentIndex === index) {
const code = this.codePointAt(i);
return String.fromCodePoint(code);
}
currentIndex++;
const point = this.codePointAt(i);
i += point > 0xffff ? 2 : 1;
}
};
三,方法三
在字符串原型上添加pointSlice方法,用于截取指定码点索引的字符。
String.prototype.pointSlice = function (start, end) {
let result = "";
for (let i = start; i < this.pointLength() && i < end; i++) {
result += this.pointAt(i);
}
return result;
};
添加完这三个方法后,以后处理这种表情字符串就容易多了。
const a = "🦐😭😠🏃";
console.log(a.pointLength()); // 4
console.log(a.pointAt(1)); // 🦐
console.log(a.pointSlice(2, 3)); // 😠
3.结语
码元与码点的问题主要会出现在一些偏僻子,表情等字符中,因为这些字符的存储空间超过了2个字节也就是超过了一个码元,所以在进行字符串处理的过程中会出现乱码的问题,通过添加三个处理码元码点的方法,就可以很好的解决这个问题。