问题背景
我们在日常开发环境中可能会遇到这样的情况:
const str = '👍😅👏😁🤗';
console.log(str.length); // 10
明明看上去是5个表情,但字符串长度却是 10。
要搞懂这个问题呢,就需要知道这两个概念了:码点和码元。
在了解码点和码元之前,有需要的可以先了解字符编码,这里就不做过多赘述了。
码元:a(字符) ---> 97(编码),编码用一个 16 位的二进制数表示,两个字节。这两个字节称为 码元(code unit)。
-
一个码元可以表示的编码范围:0 ~ 2**16(0xffff),也就是 0 ~ 65535。
-
在 Unicode 中超过一个码元的编码,会占用两个码元。比如一些繁体字、小众语言、表情符号。
码点:字符真正对应的内存空间叫做 码点(code point)。 一个码点占用一个或两个码元。
在我们日常开发中,有些时候 码元 ≠ 码点 ,如果模糊这个概念操作的话会出现下面情况:
const str = '👍😅👏😁🤗';
console.log(str.length); // 10
console.log(str[0]); // �
console.log(str.slice(1, 3)); // ��
console.log(str.slice(0, 2)); // 👍
针对码点的封装
/**
* 针对码点做一下封装
*/
// 获取码点个数(实际字符个数)
String.prototype.pointLength = function() {
let len = 0;
for(let i = 0; i < this.length; ) {
len++;
const point = this.codePointAt(i); // 获取字符串对应下标的码点。
i += point > 0xffff ? 2 : 1;
}
return len;
}
// 获取对应下标的码点的字符
String.prototype.pointAt = function(index) {
let curIndex = 0;
for(let i = 0; i < this.length; ) {
if(curIndex == index){
const point = this.codePointAt(i);
return String.fromCodePoint(point); // 根据码点获取字符
}
curIndex++;
const point = this.codePointAt(i);
i += point > 0xffff ? 2 : 1;
}
}
// 正对码点进行截取
String.prototype.pointSlice = function(start, end = this.pointLength()) {
let str = "";
for(let i = start; i < end; i++ ) {
str += this.pointAt(i);
}
return str;
}
console.log(str.pointLength()); // 输出码点的个数 5
console.log(str.pointAt(0)); // 👍
console.log(str.pointSlice(1, 3)); // 😅👏
console.log(str.slice(0, 2)); // 👍
1119

被折叠的 条评论
为什么被折叠?



