網(wǎng)(LieHuo.Net)教程 BASE64原理很簡單,但要寫出一個高效的,尤其是用JS這樣高靈活低效率的腳本,還需斟酌一翻。
先看看網(wǎng)上比較流行的版本。首先聲明64個常量字符:
以下為引用的內(nèi)容: var key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; |
這一步大家都一樣,也沒有更好的方法列出這些字符。但接下來的做法,就大有講究了。因為這里的key是一個String,所以各個版本里都大量充斥著charAt,甚至indexOf函數(shù)來操作這個key。用charAt來訪問key的第n個字符,這還在清理之中;但用indexOf來確定字符的位置,就不可原諒了。在VBScript里倒還能湊合著用,但在JS里這種做法是很糟糕的,顯然沒有把其靈活性發(fā)揮出來。何謂靈活性,用最短的話說就是多用哈希表。哈希表是JS與生俱來就有的東西,其效率是其他方法都不能相比的。顯然,在BASE64這樣數(shù)字與字符頻繁轉(zhuǎn)換的算法里,hash是該大顯身手的。
再談charAt的問題。charAt雖然不會像indexOf那樣效率數(shù)量級的下降,但也不是最優(yōu)秀的。腳本程序分兩類,一類是自己寫的,另類就是系統(tǒng)內(nèi)置在瀏覽器中的,就是所謂的[Native Code]。后者的效率當(dāng)然是遠(yuǎn)高于前者,這大家都知道。所以盡可能多讓代碼交給系統(tǒng)執(zhí)行,有時看起來可能計算量變大了,但最終的速度反倒提升了。
就說BASE64解碼的過程,參數(shù)是個String,按常規(guī)的方法就是先charAt其每個字符。如果有1萬個字符,那么charAt也就運行了1萬次。能否將多次charAt函數(shù)的執(zhí)行合并到1次本地代碼的調(diào)用上呢,當(dāng)然可以:
var arr = str.split('');
之后的str.charAt(i)就可以用arr[i]代替了。此方法雖多開辟的一塊內(nèi)存,但最終的效率還是有所提高,并且增強(qiáng)了代碼可讀性。當(dāng)然,在運行速度極快的瀏覽器比如FireFox,Chrome就沒什么區(qū)別,甚至還可能倒退。
最后就是一個層次上的問題。網(wǎng)上常有人在說BASE64如何支持中文。按照這種說法,BASE64用來編碼解碼字符串了,這與其意義多少有些偏離。BASE64的最初就是將二進(jìn)制文件轉(zhuǎn)成可見字符,在郵件里發(fā)送。因此其意義就在于二進(jìn)制與字符的轉(zhuǎn)換,而不是字符與字符的轉(zhuǎn)換。JS沒有二進(jìn)制,但可以用0-255的數(shù)組來模擬。所以:
function 編碼函數(shù)(Array[]){return String;}
function 解碼函數(shù)(String){return Array[];}
至于中文的問題,無非就是Unicode與ANSI的轉(zhuǎn)換。JS貌似沒有現(xiàn)成的轉(zhuǎn)換函數(shù),若要實現(xiàn)可以用Unicode與ANSI的對照表。但雙方的編碼/解碼都統(tǒng)一使用Unicode,也就
不存在支不支持的問題了。
最終的代碼:
以下為引用的內(nèi)容: |