你所不知道的charCodeAt與codePointAt(了解js字符串的碼元與碼點)


charCodeAt與codePointAt的用法:

  相同點:

  charCodeAt與codePointAt都是字符串實例上的方法,用途都是用來返回指定索引位字符的Unicode編碼。

  不同點:

   charCodeAt與codePointAt匹配索引位的規則不一樣。charCodeAt是根據碼元來匹配,codePointAt是根據碼點來進行匹配的。

先舉個例子:

  

 

 

     可以發現一個非常神奇的事情。

  有些中文字符𠮷 的長度不為1,並且charCodeAt與codePointAt對相同字進行處理返回的結果卻是不同的。

  有人說念‘gei給’,有人說念'ji'同吉,反正是個古文字

  這其中的原因就是charCodeAt是以一個碼元為一個索引,codePointAt是以一個碼點為一個索引進行處理的

  

  Unicode使用16位二進制來存儲文字。我們將一個16位的二進制編碼叫做一個碼元Code Unit),Unicode編碼范圍在0 - 2^16。也就是我們所說的占一個字節。

  由於技術的發展,Unicode對文字編碼進行了擴展,將某些文字擴展到了32(占用兩個碼元),並且,將某個文字對應的二進制數字叫做碼點Code Point),Unicode編碼范圍在0 - 2^32,占2個字節。

  特別要注意,碼點可以是一個碼元,也可以是兩個碼元。

  字符串的length屬性返回的是碼元。所以在對一些字符串如果要處理長度的時候要注意這一點。  

 

  𠮷這個字的Unicode編碼是\ud842\udfb7,占用了兩個碼元。

  所以當用charCodeAt(0)是匹配0位的碼元,也就是返回給我們55362。

  當用codePointAt(0)是匹配0位的碼元,codePointAt能識別出字符串的碼點,所以反回134071。

  

  𠮷.codePointAt(1)為什么返回的是57271呢?

  這是因為索引位是根據碼元,而匹配的規則是根據碼點的規則。如果后面兩位碼元是一個碼點,就會當作一個碼點來處理。

  

  總結

  charCodeAt是以碼元為單位來處理的,也就是說按照每162進制數為單位。一個162進制數就是一位,所以處理不了Unicode擴展編碼字符(322進制)。他會把322進制數當成兩個162進制數處理

  codePointAt也是以碼元位單位來處理的。與charCodeAt不同的地方是,當處理到當前位碼元時,如果超過了162進制數值的上線,他就明白這是一個322進制數,就會以322進制數當作一個來處理。

  可以通過codePointAt來判斷當前字符是是32位的碼點還是16位的碼元

 

function is32bit(char, i) {
    //如果碼點大於了16位二進制的最大值,則其是32位的
    return char.codePointAt(i) > 0xffff;
}

  同樣的,也可以通過這個方法來判斷以字符串真實的長度(碼點的長度)

function getLengthOfCodePoint(str) {
    var len = 0;
    for (let i = 0; i < str.length; i++) {
        //i在索引碼元
        if (is32bit(str, i)) {
            //當前字符串,在i這個位置,占用了兩個碼元
            i++;
        }
        len++;
    }
    return len;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM