計算機使用 8 位(bit)二進制表示一個字節(Byte),計算機內存最小尋址單位就是 1 字節。早期為了在計算機上使用同一的方式使用字符,使用無符號整數來標記字符。
ANSI(美國國家標准局)制訂了ASCII(American Standard Code for Information Interchange,美國信息交換標准代碼),使用一個字節大小的二進制數來編碼每個字符。ASCII已經被國際標准化組織(ISO)定為國際標准,稱為ISO 646標准。
一個字節為8位二進制,2的8次方為256,因此有256個字符可以用一個字節來表示(0~255),但ASCII字符集只設計了128個字符(字母、數字、一些標點符號和控制字符),因此實際上只用到7位二進制,第八位設置為0,剩下的128個編碼位置是閒置的。
有的計算機廠商可能會利用閒置的128個空位來制訂一些字符的編碼,稱為OEM字符集。例如,IBM使用多出來的128位擴展了一個ASCII 擴展表,包含了一些控制符和制表符等等,被廣泛使用在電子元件的數據通訊和存儲中,但OEM字符集不是通用的標准。
為了編碼更多的字符,2個研究字符編碼的機構合並研究成果,制訂了 unicode 字符集。unicode 字符集使用使用多個字節來為字符編碼,按使用的字節數不同制訂了不同方案,所有 unicode 編碼方案前 1 個字節(256個碼位)的編碼對應的字符都是 ASCII 字符集中的字符。
目前 unicode 編碼已經達到 64 位,使用 8 個字節標記一個字符。
如果每個字符用2個字節(16位二進制數)來標記,可以編碼 65536 個字符(2 的16次方),這基本上已經可以標記世界上所有國家的語言符號,因此,在實際中通用的是UCS-2通用字符集(Universal Character Set,UCS),由ISO制定的ISO 10646(或稱ISO/IEC 10646)標准所定義。UCS 為第一字節的128個空位增補了一個字符集,稱為 C1控制符及拉丁文補充-1 (C1 Control and Latin 1 Supplement)。
UCS-2字符集編碼法有17個位面,每個位面都用2個字節來標記字符,17個位面可以映射 1,112,064個字符,其中最常用最重要的是編號為 0 的位面,裡面包含了最常用的字符編碼,稱為基本多國語言平面BMP(Basic Multilingual Plane)。
Unicode 第 0 平面(BMP)中的編碼被劃分為不同區段,各國文字符號、控制符、制表符、圖形字符等 都有連續的分布,其中中文簡繁體區段是 4E00-9FBF。
從第1位面開始,字符的unicode編碼已經超出16位二進制數的范圍,因此UCS-2無法使用2個字節直接編碼BMP位面之外的字符。但是,在 UCS-2 編碼中,區段 UD800 到 UDFFF 的碼位是閒置的保留位,因此,可以使用這個區段中的碼位通過一定的轉換方式映射到其他位面的 unicode 編碼。
在實際的字符傳輸和存儲行為中,為了節省字節數,可能不會直接傳輸 unicode 編碼,而是使用 Unicode轉換格式(Unicode Transformation Format,簡稱為UTF),目前常見的 UTF格式有UTF-7, UTF-7.5, UTF-8, UTF-16, 以及 UTF-32,他們是由 ITTF(Internet Engineering Task Force,互聯網工程任務組)組織進行標准化的,UTF-8 和 UTF-16 編碼使用比較廣泛。
UTF-16 編碼:該編碼法在 UCS-2 第0位面字符集的基礎上利用 D800-DFFF 區段的碼位通過一定轉換方式將超出2字節的字符編碼為一對16比特長的碼元(即32bit,4Bytes),稱作代理碼對 (surrogate pair)。
例如字符“”,他處於編號'2'的位面(總共17個位面,位面編號為16進制數0-10,第0位面可以捨去編號0直接用4位16進制數編碼),碼位是A6A5,即unicode編碼為 2A6A5,它在UTF-16中的代理碼對為 d869 dea5,但是通過 js 的charCodeAt()函數只能得出高位碼對,但是這並不影響解碼軟件對字符編碼進行定位,因為這些字符的代理碼對都是成對地分布在 UD800-UDFFF 區段內的,並不存在交叉的現象,知道高位碼對也可以簡單地搜索到低位碼對。
UTF-16 編碼出現以前,UD800-UDFFF 區段的碼位可能會被一些計算機產品設計者利用,而且其他位面的字符極少用到,因此,一些軟件可能無法正確識別代理碼對,這可能會導致一些BUG。例如,python 2.6 在 UNIX 平台上便無法正確識別代理碼對。如果一個軟件聲稱自己支持UCS-2,那麼他很可能是不支持UTF-16的。
javascript 跟 java 一樣使用UTF-16編碼,因此, 實際上 javascript 程序中變量名和函數名可以使用ASCII 之外的字符,例如中文,不過網頁文件保存的編碼格式要注意,使用的編碼格式對字符編碼的范圍應當不小於 UTF-16,比如保存為 utf-8 編碼。
unicode 16 使用 16位二進制編碼字符,但是其編碼格式在書面上使用16進制(二進制寫起來太長了),在javascript中, \u 加 4個16進制字符表示一個字符的編碼(每個字節 8 位二進制對應2位十六進制,2^8 = 256 = 16^2),不足4位16進制的,高位用0補足,比如 \u55B5 表示漢字 "喵",字母 "a" 的 ASCII 碼是10進制 97,表示成 16 進制 unicode 編碼格式就是 \u0061。試試打印出來:
在 javascript 字符串的 charCodeAt 和 String.fromChartCode 中取得和使用的字節編碼都是 10 進制的,因此在 document.write 和 這些方法配合使用時需要進行進制轉換。
另外要注意的是,如果一個變量保存了一個字符的 unicode() 編碼,你想用 document.write() 打印到頁面上就需要注意了,不要將'\u' 轉義成 '\\u' ,如果轉義了,需要使用 eval() 來執行,否則將直接把編碼打印出來:
但是在表達式中,也許你想拼接出 unicode 編碼後打印字符串,這就要注意了,因為在字符串中 \u 後面必須接 4個十六進制字符才是合法的語法,所以不得不轉義:
試試下面代碼
在 js 中,可以使用 \x 加 2位16進制字符標記一個單字節的字符,例如字符 'a' 可以表示為 \x61,用法類似\u 加4位16進制編碼。
\u 加四位十六進制數 或 \x 加2位十六進制數屬於轉義字符,在 js 字符串長度中只算 1 個,轉義字符不能直接用於 HTML 文件(不會轉換後輸出,而是直接輸出轉義格式的字符串),但可以用 document.write()打印出來,因為在 js 語法范圍內,雖然表達方式不一樣,但是轉義字符和直接的字符字面量都是指同一個東西:
當向頁面顯示用戶輸入的內容是,通常我們要過濾或轉義 script 標簽以避免 XSS 攻擊,
但是,需要注意的是, \u+16進制 、\x+16進制 、字符實體如果出現在模板中的 HTML 標簽屬性中就需要特別注意了,他們會正確解碼後才賦給標簽的屬性,例如:
對標簽屬性之進行轉義時,需要對注意,是比較下面2個做法:
5、八進制轉義字符
js 字符串中,\ 開始後接正數,可能被解析為8進制轉義字符。
一個八進制轉義字符形成的條件是:斜線後面接的整數最長3位,至少1位,單個數字的字面值不大於8。
如果過不滿足任意一項,都將結束一個字符的解釋,開始新字符的解釋。八進制轉義字符的10進制數字字面值最大值為377,即 '\377' 被解析為一個字符,'\378' 被解析為2個字符: '\37' 和 '8' :
更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2014-09/106211p2.htm