前端最基礎的就是 HTML+CSS+Javascript
。掌握了這三門技術就算入門,但也僅僅是入門,現在前端開發的定義已經遠遠不止這些。前端小課堂(HTML/CSS/JS
),本着提升技術水平,打牢基礎知識的中心思想,我們開課啦(每週四)。
編碼解碼對於web開發來說,有可能最常見的是URL編碼(encode
decode
)。
ASCII 編碼
計算機處理的內容是二進制,對應開和關的狀態。如果要處理文本,也是把文本轉換爲數字然後做比對。最早的計算機在設計時採用8個比特(bit)作爲一個字節(byte)。
一個字節能表示的最大的整數就是255(0b11111111==255
)。這255個數字被用來表示大小寫英文字母、數字和一些符號,這個編碼表被稱爲ASCII編碼,比如大寫字母A的編碼是65,小寫字母a的編碼是97。
GB2312編碼
如果要表示中文,顯然ASCII的一個字節是不夠的,至少需要兩個字節,而且還不能和ASCII編碼衝突。
所以,中國製定了GB2312編碼(國標2312編碼),用來把中文編進去。
Unicode 編碼
Unicode(萬國碼),包括字符集、編碼方案等。
Unicode 是爲了解決傳統的字符編碼方案的侷限而產生的,它爲每種語言中的每個字符設定了統一併且唯一的二進制編碼,以滿足跨語言、跨平臺進行文本轉換、處理的要求。1990年開始研發,1994年正式公佈。
Unicode通常用兩個字節表示一個字符,原有的英文編碼從單字節變成雙字節,只需要把高字節全部填爲0就可以。目前的Unicode字符集爲0x0000
至0x10FFFF
,分爲17組編排,,每平面擁有65536個碼位,共1114112個碼位。
Unicode 到目前爲止所定義的十七個平面中,第0平面(BMP)最爲重要。
中文範圍 4E00-9FA5
:CJK 統一表意符號 (CJK Unified Ideographs)
在Unicode中:“李”字對應的數字是26446
(十進制),十六進制表示爲0x674e
。
UTF 編碼系列
Unicode 只是一個大的合集,UTF-8、UTF-16、UTF-32纔是將數字轉換到程序數據的編碼方案。
UTF是Unicode Transformation Format的縮寫,可以翻譯成Unicode字符集轉換格式,即怎樣將Unicode定義的數字轉換成程序數據。
UTF-8
UTF-8的特點是對不同範圍的字符使用不同長度的編碼,這點極大的縮小了文件的大小。當然,也會造成一定的性能浪費,
對於0x00-0x7F之間的字符,UTF-8編碼與ASCII編碼完全相同。
對於超過區間的字符,最高位非0,10
標識當前屬於前面字節的描述字節。110
標明這是兩個字節的,後面還會跟着一個字節。
UTF-8編碼的最大長度是4個字節。從表格中可以看到,4字節模板有21個x,即可以容納21位二進制數字。Unicode的最大碼位0x10FFFF也只有21位。
Unicode編碼(十六進制) | UTF-8 字節流(二進制) |
---|---|
000000-00007F |
0xxxxxxx |
000080-0007FF |
110xxxxx 10xxxxxx |
000800-00FFFF |
1110xxxx 10xxxxxx 10xxxxxx |
010000-10FFFF |
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
“李” \u674e
|
11100110 10011101 10001110 |
“A” \u0041
|
01000001 |
UTF-16
UTF-16編碼以16位無符號整數爲單位。我們把Unicode編碼記作U。
如果U<0x10000,UTF-16編碼(二進制)就是對應的16位無符號整數。
如果U≥0x10000,先計算U'=U-0x10000
,然後將U'寫成二進制形式:yyyy yyyy yyxx xxxx xxxx
,U的UTF-16編碼(二進制)就是:110110yyyyyyyyyy 110111xxxxxxxxxx
。
這裏,你會好奇,因爲第二條規則會和第一條規則重複。爲了將編碼區分開來,Unicode
編碼的設計者將0xD800-0xDFFF
保留下來,並稱爲代理區(Surrogate)
// D800-DB7F High Surrogates 高位替代
// 指UTF-16編碼中。兩個位置中的第一個位置
(0xD800).toString(2) == 1101100000000000
(0xDB7F).toString(2) == 1101101101111111
// DC00-DFFF Low Surrogates 低位替代
// 指UTF-16編碼中。兩個位置中的第二個位置
(0xDC00).toString(2) == "1101110000000000"
(0xDFFF).toString(2) == "1101111111111111"
// DB80-DBFF High Private Use Surrogates 高位專用替代
(0xDB80).toString(2) == "1101101110000000"
(0xDBFF).toString(2) == "1101101111111111"
UTF-32
UTF-32編碼以32位無符號整數爲單位。Unicode的UTF-32編碼就是其對應的32位無符號整數。
字節序
字節序有兩種,分別是“大端”(Big Endian, BE)和“小端”(Little Endian, LE)。
根據字節序的不同,UTF-16可被實現爲UTF-16LE或UTF-16BE,UTF-32可被實現爲UTF-32LE或UTF-32BE。
Unicode編碼 | UTF-16LE | UTF-16BE | UTF32-LE | UTF32-BE |
---|---|---|---|---|
0x006C49 | 49 6C | 6C 49 | 49 6C 00 00 | 00 00 6C 49 |
0x020C30 | 43 D8 30 DC | D8 43 DC 30 | 30 0C 02 00 | 00 02 0C 30 |
Unicode標準建議用BOM(Byte Order Mark)來區分字節序,即在傳輸字節流前,先傳輸被作爲BOM的字符“零寬無中斷空格”。這個字符的編碼是FEFF,而反過來的FFFE(UTF-16)和FFFE0000(UTF-32)在Unicode中都是未定義的碼位,不應該出現在實際傳輸中。
UTF編碼 | Byte Order Mark (BOM) |
---|---|
UTF-8 without BOM | 無 |
UTF-8 with BOM | EF BB BF |
UTF-16LE | FF FE |
UTF-16BE | FE FF |
UTF-32LE | FF FE 00 00 |
UTF-32BE | 00 00 FE FF |
URL編碼/解碼
url編碼是一種瀏覽器用來打包表單輸入的格式。
瀏覽器將表單中獲取到的內容,以name=value
參數編碼,作爲URL的一部分或者放入body發給服務器。轉換成如:a=1&b=2
。
基於上面的規則,=
或者&
都會造成解析異常。所以特殊的字符(不是簡單的七位ASCII,如漢字,關鍵詞),會以%XX
這個格式轉義,比如:
字符 | encode編碼 | utf-8編碼 |
---|---|---|
= |
%3D |
00111101 |
李 |
%E6%9D%8E |
11100110 10011101 10001110 |
// 轉換代碼
encodeURIComponent('李').replace(/%([0-9a-f]{2})/gi, (v,group1)=>parseInt(group1,16).toString(2)+' ') // "11100110 10011101 10001110 "
encodeURIComponent('=').replace(/%([0-9a-f]{2})/gi, (v,group1)=>parseInt(group1,16).toString(2).padStart(8,'0')+' ') //"00111101 "
微信公衆號:前端linong