美文网首页
codePointAt()与charCodeAt()方法区别

codePointAt()与charCodeAt()方法区别

作者: 最x程序猿 | 来源:发表于2020-01-20 16:55 被阅读0次

    charCodeAt与codePointAt的用法:

    • 相同点:
        charCodeAt与codePointAt都是字符串实例上的方法,用途都是用来返回指定索引位字符的Unicode编码。
    • 不同点:
         charCodeAt与codePointAt匹配索引位的规则不一样。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 个字节储存的字符,根据字符串码元的位置得到其码点。

    • 𠮷这个字的Unicode编码是\ud842\udfb7,占用了两个码元。
    • 所以当用charCodeAt(0)是匹配0位的码元,前两个字节值 55362,toString(16)是ud842。
    • 当用codePointAt(0)是匹配0位的码点,codePointAt能识别出字符串的码点,所以反回134071。

    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

    欢迎大佬指点

    相关文章

      网友评论

          本文标题:codePointAt()与charCodeAt()方法区别

          本文链接:https://www.haomeiwen.com/subject/wtrjzctx.html