codePointAt()与charCodeAt()方法区别

2020-01-20  本文已影响0人  最x程序猿

charCodeAt与codePointAt的用法:

JavaScript 内部,字符以 UTF-16(字符用两个字节或四个字节表示) 的格式储存,码点范围介于U+0000到U+FFFF,每个字符固定为2个字节,一个码元。对于那些需要4个字节储存的字符(Unicode 码点大于0xFFFF的字符),两个码元,JavaScript 会认为它们是两个字符。

在计算机发展的早期,由于存储空间宝贵,Unicode使用16位二进制来存储文字。也就是一个码元来存储一个文字。
由于技术的发展,Unicode对文字编码进行了扩展,将某些文字扩展到了32位(占用两个码元),而一个文字对应的二进制数字是一个码点,所以使用32位二进制数字存储的文字(一个码点=两个码元)
特别要注意,码点可以是一个码元,也可以是两个码元。

字符串的length属性返回的是码元。所以在对一些字符串如果要处理长度的时候要注意这一点。

let str="A";              
let strSpecial = "𠮷"; 
console.log(str.length);               // 1
console.log(strSpecial.length);       // 2

(1)length属性返回对应几个码元字符
(2)str的Unicode是\u0041\只有一个字符,strSpecial Unicode编码是\ud842\udfb7,双字节两个码元,js识别为2个字符

let str="A";
let strSpecial = "𠮷"; 
console.log(str.charCodeAt(0));               // 65
console.log(str.codePointAt(0));              // 65
console.log(strSpecial.charCodeAt(0));        // 55362
console.log(strSpecial.codePointAt(0));       // 134071

ES6 提供了codePointAt(0)方法,能够正确处理 4 个字节储存的字符,根据字符串码元的位置得到其码点。

codePointAt方法返回的是码点的十进制值,如果想要十六进制的值,可以使用toString方法转换一下。

let a = 'A';
 let s = '𠮷';
 a.codePointAt(0).toString(16) 
"41"
 s.codePointAt(0).toString(16) 
"20bb7"

但是这里需要注意参数:

let strSpecial = "𠮷"; 
console.log(strSpecial.charCodeAt(1));           
console.log(strSpecial.codePointAt(0));    
console.log(strSpecial.codePointAt(1));
image.png

codePointAt(1)与charCodeAt(1)的返回值相同,都是返回后两个字节的码元值。
这是因为索引位是根据码元,而匹配的规则是根据码点的规则。如果后面两位码元是一个码点,就会当作一个码点来处理。

let str="A";
let strSpecial = "𠮷A"; 
console.log(str.charCodeAt(0));
console.log(strSpecial.codePointAt(0));
console.log(strSpecial.codePointAt(1));
console.log(strSpecial.codePointAt(2));
image.png

strSpecial.codePointAt(1)取的不是A的字符值,是strSpecial后两个字节的码元值,而.codePointAt(2)才取得A的字符值,与str.charCodeAt(0)一样。

解决顺序问题的配套办法是使用for...of循环,因为它可以识别UTF-32(字符用四个字节表示,两个码元)

let strSpecial = "𠮷"; 
for (let char of strSpecial) {
  console.log(char.codePointAt(0));
}

关于for of可以参阅JavaScript for of 循环一章节。
codePointAt()方法是测试一个字符由两个字节还是由四个字节组成的最简单方法。

function is32Bit(c) {
  // 如果码点大于了16位二进制的最大值,则其是32位的
  return c.codePointAt(0) > 0xFFFF;
}
is32Bit("𠮷") // true
is32Bit("a") // false

有用的字符编码笔记:http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html

欢迎大佬指点

上一篇下一篇

猜你喜欢

热点阅读