JavaScript字符串长度[String].length以及码元[Code Point]和码点[Code Unit]的详解
码元,码点出现的问题
码元(Code Point):我们将一个16位的二进制编码叫做一个码元
码点(Code Unit):我们将某个文字对应的二进制数字叫做码点
由于码元,码点产生的问题—[string].length
const sex = '男';
console.log(sex.length); //1
//测试字符串是否只有一个字符
console.log(/^.$/.test(sex)); //true
//测试字符串是否只有两个字符
console.log(/^..$/.test(sex)); //false
// '𠮷':同“吉”,吉的异体字
const text = '𠮷';
console.log(text.length); //2
//测试字符串是否只有一个字符
console.log(/^.$/.test(text)); //false
//测试字符串是否只有两个字符
console.log(/^..$/.test(text)); //true
运行代码打印出: 1 true false 2 false true
出现上述结果的原因:
[string].length:默认返回的是字符串的码元的数量
上面代码中的正则表达式默认匹配的也是码元的数量
(1)在计算机发展的早期,由于存储空间宝贵,Unicode使用16位二进制来存储文字。也就是一个码元来存储一个文字。
(2)后来,由于技术的发展,Unicode对文字编码进行了扩展,将某些文字扩展到了32位(占用两个码元),而一个文字对应的二进制数字是一个码点,所以使用32位二进制数字存储的文字(一个码点=两个码元)
"男":使用的是16位的二进制编码存储(1个码元)
"𠮷":使用的是32位的二进制编码存储(2个码元)
[string].charCodeAt(0).toString(16) 可以取出第一个码元
解决:
ES6对Unicode编码提供了更好的支持,为字符串提供了方法:codePointAt,根据字符串码元的位置得到其码点。
[string].codePointAt(0).toString(16) 可以取出第一个码点
同时,ES6为正则表达式添加了一个flag: u,如果添加了该配置,则匹配时,使用码点匹配
下面代码用码点的编码判断文字是不是32位的(两个码元)
const sex = '男';
const text = '𠮷';
/**
* 判断字符串str的某个字符,是不是32位
* i是码元位置
*/
function is32Bit(str, i) {
return str.codePointAt(i) > 0xffff;
}
console.log(sex, is32Bit(sex,0)); //false
console.log(text, is32Bit(text,0)); //true
未完待续…