Unicode是一個字符庫,裏面收錄了全世界絕大多數的字符,並用0,1,2,,,n對每個字符進行惟一的編號,這些編號咱們稱之爲碼點。html
當前Unicode字符被分爲17組編排,每組稱爲一個平面,每一個平面擁有65536(即2^16)個字符。函數
包含最前面的65536個字符,即碼點範圍從0 ~ 2^16 - 1,稱爲基本多文種平面(Basic Multilingual Plane, BMP)。全部最多見的字符都在這個平面裏面,這是Unicode最早定義和公佈的一個平面。剩下的16組平面稱爲輔助平面。編碼
17組平面能夠包含2^(5+16)個字符,即須要21位的編碼空間,比3字節略少。設計
Unicode只是一個符號集,它只規定了符號的二進制代碼,卻沒有規定這個二進制代碼應該如何存儲。考慮一些極端的例子: 1.用二進制代碼表示Unicode中碼點爲1的字符,使用1個字節就是00000001;使用2個字節就是00000000 00000001;使用3個字節就是00000000 00000000 00000001;使用4個字節就是00000000 00000000 00000000 00000001。很顯然若是使用四個字節存儲該字符,將形成極大的空間浪費。 2.用二進制代碼表示Unicode中碼點爲100000的字符,至少須要3個字節,即 00000001 10000110 10100000,固然也能夠用4個字節00000000 00000001 10000110 10100000來表示。3d
考慮到系統平臺的差別以及出於節省存儲空間的因素,Unicode並無對使用多少個字節來存儲一個字符對應的二進制代碼作出強制的規定,所以Unicode的實現方式有多種,而Unicode的實現方式稱爲Unicode轉換格式(Unicode Transformation Format,簡稱爲UTF)code
咱們平時常見的編碼方案,好比ASCII、UTF-八、UTF-1六、UTF-32都是對Unicode的不一樣實現。 ASCII編碼:使用1個字節來表示一個字符,該編碼方案僅適用於對Unicode中的前128位字符,適用於西文文檔。 UTF-32編碼:使用4個字節表示一個字符,理論上4個字節可表示2^32 = 4,294,967,296,遠超當今的Unicode所接納的字符,所以能夠徹底對應Unicode編碼。該編碼的優勢是轉換規則簡單直觀,查找效率高,可是也有致命的缺點,浪費空間,一樣內容的英語文本,它會比ASCII編碼大四倍,目前基本上沒有什麼場景去使用這種編碼方式。 UTF-8編碼:在衡量一個程序設計好壞時,時間和空間這兩個維度的複雜度是永遠繞不開的。若是你內存足夠大,你徹底能夠用空間換時間,可是從編碼設計角度來講,人們真正須要的仍是一種節省空間的編碼方案,這直接致使了目前使用最多的utf-8編碼方案的誕生。UTF-8是一種變長的編碼方法,字符長度從1個字節到4個字節不等。越是經常使用的字符,字節越短,最前面的128個字符,只使用1個字節表示,與ASCII碼徹底相同(爲了方便書寫,後面涉及到的二級制代碼統一用16進製表示)。orm
UTF-16編碼:介於UTF-32與UTF-8之間,同時結合了定長和變長兩種編碼方法的特色。它的編碼規則很簡單,基本平面的字符佔用2個字節,輔助平面的字符佔用4個字節。也就是說,UTF-16的編碼長度要麼是2個字節(U+0000到U+FFFF),要麼是4個字節(U+010000到U+10FFFF)。前面介紹過了基本平面包含了 65536 = 2^16 個字符,所以用兩個字節去表示很是合適。cdn
那麼緊接着問題就來了,計算機怎麼知道當前的這個字符,它應該讀取兩個字節仍是四個字節呢?下面具體來講對應的解決方案。具體來講,輔助平面的字符位共有2^20(即 2^4(輔助平面個數) x 2^16(每一個輔助平面理論上可容納的字符個數))個,就是說,對應這些字符至少須要20個二進制位。UTF-16將這20位拆成兩半,前10位映射在U+D800到U+DBFF(即56319 - 55296 = 2^10,空間大小2^10),稱爲高位(H),後10位映射在U+DC00到U+DFFF(計算同前面的高位,空間大小2^10),稱爲低位(L)。這意味着,一個輔助平面的字符,被拆成兩個基本平面的字符表示。當咱們遇到兩個字節,發現它的碼點在U+D800到U+DBFF之間,就能夠判定: 1.緊跟在後面的兩個字節的碼點,應該在U+DC00到U+DFFF之間 2.這四個字節必須放在一塊兒解讀htm
因爲歷史的緣由,JavaScript使用UCS-2編碼,該編碼方案使用2個字節表示一個字符。該編碼方案對於Unicode中大於2個字節的字符處理帶了不少的侷限性,好比一個佔用4個字節的字符,若是用使用UCS-2編碼方案處理,會被處理爲兩個字符,這會致使字符串的長度以及使用字符相關的函數,都沒法獲得正確的返回結果,要想獲得正確的結果,必須使用polyfill部署本身的版本。blog
主要參考阮一峯的博客http://www.ruanyifeng.com/blog/2014/12/unicode.html