码点和码元

问题背景

我们在日常开发环境中可能会遇到这样的情况:

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));      // 👍

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值