计算机存储原理:
a —> 97:将字符转换为数字(ASCII码)的过程称为编码,对于字符编码一般使用的是UTF-16
16位二进制 – 2个字节(1个字节8位二进制)
获取字符串占用的内存空间:字符串length * 2 = 占用的字节数
16位二进制存储范围:2 ** 16 = 65536:0 - 65535 ---> 0000 - ffff(16进制)
当一个16位存不下时,会用两个16位进行存储
两个16位二进制存储范围:2 ** 32 = 4294967296:0 - 4294967295
一个16位存储空间是一个存储的基本单元:Code Unit - 码元
一个文字可能占1个16位,也可能占2个16位:Code Point - 码点
字符串的length
— 字符串的码元数量
通过字符串下标 — 获取的也是码元
const str = '🐕❤🏠🚗💴';
str.codePointAt(0);
str.codePointAt(index)
:获取字符的码点,与65535进行比较,大于65536时表示占用两个码元,小于等于表示占用一个码元。
- 接收参数为想要获取的目标字符(码点)的开始下标
'🐕'.codePointAt(0);
// 128021
'🐕'.codePointAt(1);
// 56341
String.fromCodePoint(number)
:将码点转换为字符
- 接收参数为想要转换的目标码点
String.fromCodePoint(128021);
// 🐕
const str = "🐕❤🏠🚗💴z";
/**
* 获取字符串的码点长度 -- 实际能看见的字符长度
*/
String.prototype.pointLength = function () {
let len = 0;
for (let i = 0; i < this.length; ) {
const codePoint = this.codePointAt(i);
i += codePoint > 65535 ? 2 : 1;
// i += codePoint > 0xffff ? 2 : 1; // 16进制
len++;
}
return len;
};
/**
* 获取字符串的码点长度 -- 实际能看见的字符长度
* @param {string} str 目标字符串
* @returns {number} 字符长度
*/
const pointLength = (str) => {
let len = 0;
for (let i = 0; i < str.length; ) {
const codePoint = str.codePointAt(i);
i += codePoint > 65535 ? 2 : 1;
// i += codePoint > 0xffff ? 2 : 1; // 16进制
len++;
}
return len;
};
/**
* 获取字符串对应下标的字符 -- 码点下标
* @param {number} index 想要获取的目标字符下标
* @returns {string} 对应字符
*/
String.prototype.pointAt = function (index) {
let curIndex = 0; // 码点的下标
for (let i = 0; i < this.length; ) {
const codePoint = this.codePointAt(i);
if (curIndex === index) {
return String.fromCodePoint(codePoint);
}
i += codePoint > 65535 ? 2 : 1;
curIndex++;
}
};
/**
* 获取字符串对应下标的字符 -- 码点下标
* @param {string} str 目标字符串
* @param {number} index 获取的码点下标对应的字符
* @returns {string} 对应字符
*/
const pointAt = (str, index) => {
let curIndex = 0;
for (let i = 0; i < str.length; ) {
const codePoint = str.codePointAt(i);
if (curIndex === index) {
return String.fromCodePoint(codePoint);
}
i += codePoint > 65535 ? 2 : 1;
curIndex++;
}
};
/**
* 字符串截取,根据码点下标进行截取
* @param {number} start 开始位置,默认为字符串开始
* @param {number} end 结束位置,默认为字符串码点长度的长度
* @returns {string} 截取的目标字符串结果
*/
String.prototype.sliceByPoint = function (start = 0, end = this.pointLength()) {
let result = "";
for (let i = start; i < end; i++) {
result += this.pointAt(i); // i是码点下标
}
return result;
};
/**
* 字符串截取,根据码点下标进行截取
* @param {string} str 源字符串
* @param {number} start 开始截取下标,默认为字符串开始
* @param {number} end 截取结束下标,默认为字符串码点长度
* @returns {string} 截取的目标字符串结果
*/
const sliceByPoint = (str, start = 0, end = pointLength(str)) => {
let result = "";
for (let i = start; i < end; i++) {
console.log(i, end);
result += pointAt(str, i);
}
return result;
};
// console.log(pointLength(str));
// console.log(str.pointAt(0));
// console.log(str.sliceByPoint(0, 3))
// console.log(str.pointAt(2));
// console.log(pointAt(str, 2));
// console.log(sliceByPoint(str, 0, 3));