javaScript中的Unicode

javaScript中的Unicode

踩坑 在作某個業務的時候,後端童鞋給到的某個字段的值大概都長這樣 javascript "\n#\u0008\u0005\u0012\u001f\u0012\u001d\u0005星球大戰\u0006:原力覺醒\n\u000f\u0008\u0006\u0012\u000b\u0012\t張學友\n\n\u0008\u0003\u0012\u0006\u0012\u0004Dior\n\u0012\u0008\u0007\u0012\u000e\u0012\u000c英雄聯盟" 對於這樣的數據,我是拒絕的。對於這些 unicode,怎麼解析呢?它究竟是什麼?

什麼是編碼

其實編碼原理很簡單,在計算中並不是直接存儲字符(英文、中文等),而是存儲這些字符對應的一個數字,這些字符在網絡傳輸的時候,也是傳輸字符對應的數字,編碼就是將字符轉化成相應的數字。javascript

ASCII

大學C語言入門課程最早學習的知識,它用了一個字節的7位表示一個字符,好比字符A的ASCII碼是65。ASCII碼只用了7個bit編碼,註定能編碼的字符不多,只有128個。java

Unicode編碼

ASCII編碼只能編碼128個字符,而中國漢子就有6000 +,這樣顯然不夠的,而後中國推出GBK 編碼,用了兩個字節來編碼。中國編碼用了GBK,那其餘國家呢?因而爲了統一,推出了Unicode編碼。在1991年推出了UCS統一編碼,實際應用的是USC-2,用了2個字節來編碼,能編碼65536個字符。JavsScript中的編碼就是用的這個編碼方式。正則表達式

編碼都是不涉及計算機存儲,傳輸的。可是在遇到兩個字節編碼的字符的時候,有個系統是大端順序讀取,Windows就是這樣,而Mac上是按照小端順序讀取。若是沒有個轉化格式,那麼就亂了,此時UTF(Unicode Transformation Format,簡稱爲UTF)就產生了。所以,UTF-16使用了大端序(Big-Endian,簡寫爲UTF-16 BE)、小端序(Little-Endian,簡寫爲UTF-16 LE)以及BOM(byte order mark)的概念。避免上述狀況的出現。後端

JavaScript中的編碼

JavaScript剛建立出來的時候,只有USC-2編碼方式可選,因此就一隻用了這個編碼方式。上文也提到USC-2一開始使用了兩個字節來編碼,可以編碼65536個字符,從0x0 - 0xFFFF,這個也被稱爲基本平面(BMP-—Basic Multilingual Plane)。可是後來發現這樣的Unicode編碼也是不夠用,擴展了其餘補充平面,從0x010000 - 0x10FFFF,共16個。對於補充平面的字符。對於UTF-16編碼方式來講,在0x0 - 0xFFFF之間的編碼方式直接使用了2個字節,而補充平面使用了4個字節來編碼,其中前兩個字節範圍是0xD800 - 0xDBFF,後兩個字節範圍是0xDC00 - 0xDFFF。經過下面的方式完成映射:網絡

H = Math.floor((c-0x10000) / 0x400)+0xD800 
L = (c – 0x10000) % 0x400 + 0xDC00

USC-2編碼的那些坑

var text = "𠮷"
console.log(text.length) // 2
console.log(/^.$/.test(text)) // false
console.log(text.split('').reverse()) // ["�", "�"]
console.log(String.fromCharCode(text.codePointAt(0))) // "�"

(1)判斷長度失效

對於ES5來講,能夠將此類轉化如下學習

var regexAstralSymbols = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g; // 匹配UTF-16的代理對
 
function countSymbols(string) {
    return string
        .replace(regexAstralSymbols, '_')
        .length;
}
countSymbols("𠮷"); // 1

對於ES6來講編碼

function codePointLength(text) {
    var result = text.match(/[\s\S]/gu);
    return result ? result.length : 0;
}
codePointLength("𠮷") // 1

(2)正則表達式

console.log(/^.$/u.test(text)); // true

字符反轉

function reverse(string) {
    return Array.from(string).reverse().join('');
}
reverse("𠮷") // "𠮷"

String.fromCharCode

var text = "𠮷";
console.log(text.codePointAt(0)) // 0x20bb7 (unicode)
var hightByte = text.charCodeAt(0) // 0xd842
var lowByte = text.charCode(1) // 0xdfb7
console.log(String.fromCharCode(hightByte, lowByte)) // "𠮷"
console.log(String.fromCodePoint(text.codePointAt(0))) // "𠮷"

寫在最後

最後發現這樣的編碼沒法編碼成想要的字符,最後讓後端童鞋編碼成base64編碼,而後解碼。代理

相關文章
相關標籤/搜索