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
大學C語言入門課程最早學習的知識,它用了一個字節的7位表示一個字符,好比字符A的ASCII碼是65。ASCII碼只用了7個bit編碼,註定能編碼的字符不多,只有128個。java
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剛建立出來的時候,只有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
var text = "𠮷" console.log(text.length) // 2 console.log(/^.$/.test(text)) // false console.log(text.split('').reverse()) // ["�", "�"] console.log(String.fromCharCode(text.codePointAt(0))) // "�"
對於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
console.log(/^.$/u.test(text)); // true
function reverse(string) { return Array.from(string).reverse().join(''); } reverse("𠮷") // "𠮷"
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編碼,而後解碼。代理