前面一篇文檔《中文化和國際化問題權威解析之五:URL編碼/Misc》主要是從服務端、瀏覽器兩個角度來看待URL編碼;除此之外,我們還可能在客戶端執(zhí)行一些js腳本來進行URL編碼,與此相關的最主要的三個js function為:
escape():采用ISO Latin字符集對指定的字符串進行編碼。所有的空格符、標點符號、特殊字符以及其他非ASCII字符都將被轉(zhuǎn)化成%xx格式的字符編碼(xx等于該字符在字符集表里面的編碼的16進制數(shù)字)。比如,空格符對應的編碼是%20。unescape方法與此相反。不會被此方法編碼的字符: @ * / +
encodeURI():把URI字符串采用UTF-8編碼格式轉(zhuǎn)化成escape格式的字符串。不會被此方法編碼的字符:! @ # $& * ( ) = : / ; ? + '
encodeURIComponent():把URI字符串采用UTF-8編碼格式轉(zhuǎn)化成escape格式的字符串。與encodeURI()相比,這個方法將對更多的字符進行編碼,比如 / 等字符。所以如果字符串里面包含了URI的幾個部分的話,不能用這個方法來進行編碼,否則 / 字符被編碼之后URL將顯示錯誤。不會被此方法編碼的字符:! * ( )
這是目前互聯(lián)網(wǎng)上隨處可見的對這3個function的解釋,很多文章里面還附帶了英文便于對照;對escape還有一些文檔這么解釋:直接使用"%"加字符的Unicode內(nèi)碼來表示字符;
比如:escape("我是中國人") = %u6211%u662F%u4E2D%u56FD%u4EBA
這幾句話MS很簡單、明了,但細思之下發(fā)現(xiàn)有幾點疑惑,比如:
于是,我用如下這段html代碼進行測試,文件格式為ANSI/ASCII;
將代碼中charset設置為不同的字符編碼,得到的結(jié)果卻是完全不一樣!
測試結(jié)果為:
字符編碼 | 測試結(jié)果 |
charset=UTF-8 | /%u0392%3F%3F /%CE%92?? %2F%CE%92%3F%3F http%3A//mall.alisoft.com/%u0392%3F%3F http://mall.alisoft.com/%CE%92?? http%3A%2F%2Fmall.alisoft.com%2F%CE%92%3F%3F |
charset=GBK | /%u6211%u7231 /%E6%88%91%E7%88%B1 %2F%E6%88%91%E7%88%B1 http%3A//mall.alisoft.com/%u6211%u7231 http://mall.alisoft.com/%E6%88%91%E7%88%B1 http%3A%2F%2Fmall.alisoft.com%2F%E6%88%91%E7%88%B1 |
charset=ISO-5899-1 | /%CE%D2%B0%AE /%C3%8E%C3%92%C2%B0%C2%AE %2F%C3%8E%C3%92%C2%B0%C2%AE http%3A//mall.alisoft.com/%CE%D2%B0%AE http://mall.alisoft.com/%C3%8E%C3%92%C2%B0%C2%AE http%3A%2F%2Fmall.alisoft.com%2F%C3%8E%C3%92%C2%B0%C2%AE |
當把文件格式修改為UTF-8/Unicode時,測試結(jié)果和上面不一樣;同樣設置三種不同charset進行測試,結(jié)果卻是完全相同,和文件格式為ANSI/ASCII、charset=GBK時的結(jié)果完全一樣!
從上面幾項測試結(jié)果信息來回答前面提出的幾個問題:
對于第1點:顯然,ISO Latin并不是指ISO-8859-1編碼,但也并不一定是Unicode內(nèi)碼!按照我的分析,只有當文件格式與charset相匹配時,該三個function才能正常工作(當不匹配時執(zhí)行結(jié)果也是亂碼);
對于第2點:MS是無關的,編碼結(jié)果依賴于文件格式!當使用ANSI/ASCII保存時,因為系統(tǒng)編碼為GBK,所以此時文件實際上是以GBK編碼保存的,所以在function執(zhí)行時會出現(xiàn)第一種測試情況;而當文件以UTF/Unicode保存時,各種charset情況下都能正常執(zhí)行,估計是js引擎在底層做了很多事情;
總結(jié)起來,要想讓這3個function正常工作,最好是用Unicode系列文件格式,這樣就和charset無關了;若采用ANSI/ASCII文件格式,則charset需要設置為與系統(tǒng)默認編碼一致,否則function執(zhí)行會出現(xiàn)意想不到的結(jié)果;在此基礎上,三個function執(zhí)行的結(jié)果可以解釋為:
Escape:將非ASCII @ * / +轉(zhuǎn)義為%uxxxx格式,其中xxxx為字符的Unicode內(nèi)碼;
其他兩個function描述不變,直接轉(zhuǎn)換成UTF-8的%格式,只不過兩者的編碼字符范圍不一樣而已。