欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

javascript parseInt 大改造

 更新時(shí)間:2009年09月27日 07:10:45   作者:  
還隱約記得第一次遇到 parseInt這個(gè)詭異問題的時(shí)候,以為發(fā)現(xiàn)了IE的BUG,興奮不已。
還隱約記得得知了來龍去脈,為自己掌握了一個(gè)經(jīng)驗(yàn)而歡呼雀躍。

還隱約記得被這同一問題折磨了無數(shù)次后,無奈與痛下決心的心境。

首先我必須感謝那些即使這個(gè)問題我強(qiáng)調(diào)過無數(shù)次,也依然反復(fù)重復(fù)類似錯(cuò)誤的人們。
沒有他們反復(fù)犯錯(cuò)的鼓勵(lì),或許我不會認(rèn)真考慮這個(gè)問題的解決方案。
其次,必須感謝《JavaScript高級程序設(shè)計(jì)》的作者和譯者。
在這里我得到了解決該問題的啟示,不然我依然要每每強(qiáng)調(diào)使用parseInt時(shí)應(yīng)注意什么。


同時(shí),希望在這里不僅僅留下一個(gè)解決方案。
解決問題的思路與想法,以及對問題舉一反三的經(jīng)驗(yàn)在這里保留一下。

問題:
很久以前發(fā)生的問題不想再痛苦的回憶。
這次的問題很簡單。兩個(gè)月份比較的時(shí)候,因?yàn)樵路菔菑淖址谐槿〕鰜淼模?于是用parseInt轉(zhuǎn)換了一下。
結(jié)果parseInt("08")之后結(jié)果是 0
原因請參看以下《JavaScript高級程序設(shè)計(jì)》19~20頁對 parseInt函數(shù)的講解。

parseInt() 方法還有基模式,可以把二進(jìn)制、八進(jìn)制、十六進(jìn)制或其他任何進(jìn)制的字符串轉(zhuǎn)換成整數(shù)。
基是由 parseInt() 方法的第二個(gè)參數(shù)指定的,所以要解析十六進(jìn)制的值,需如下調(diào)用 parseInt() 方法:
復(fù)制代碼 代碼如下:

var iNum1 = parseInt("AF", 16); //返回 175

當(dāng)然,對二進(jìn)制、八進(jìn)制甚至十進(jìn)制(默認(rèn)模式),都可以這樣調(diào)用 parseInt() 方法:
復(fù)制代碼 代碼如下:

var iNum1 = parseInt("10", 2); //返回 2
var iNum2 = parseInt("10", 8); //返回 8
var iNum3 = parseInt("10", 10); //返回 10

如果十進(jìn)制數(shù)包含前導(dǎo) 0,那么最好采用基數(shù) 10,這樣才不會意外地得到八進(jìn)制的值。例如:

var iNum1 = parseInt("010"); //返回 8
var iNum2 = parseInt("010", 8); //返回 8
var iNum3 = parseInt("010", 10); //返回 10

在這段代碼中,兩行代碼都把字符 "010" 解析成一個(gè)數(shù)字。

第一行代碼把這個(gè)字符串看作八進(jìn)制的值,解析它的方式與第二行代碼(聲明基數(shù)為 8)相同。最后一行代碼聲明基數(shù)為 10,所以 iNum3 最后等于 10。

初試身手:
以前的解決方法是讓大家都拋棄 parseInt函數(shù),全部以parseFloat來替換。
但是作為人“孰能無忘”?
最好的辦法莫過于保留parseInt的“形”,廢了parseInt的“神”。
于是我想到了《JavaScript高級程序設(shè)計(jì)》87~88頁關(guān)于“重定義已有方法”的說明。
3.6.2 重定義已有方法
就像能給已有的類定義新方法一樣,也可重定義已有的方法。
如前一章所述,函數(shù)名只是指向函數(shù)的指針,因此可以輕易地使它指向其他函數(shù)。如果修改了本地方法,如 toString() ,會出現(xiàn)什么情況呢?

Function.prototype.toString = function () {
return "Function code hidden";
}
前面代碼完全合法,運(yùn)行結(jié)果完全符合預(yù)期:
function sayHi () {
alert("你好!");
}
alert(sayHi.toString()); //輸出"Function code hidden"
也許你還記得,第 2 章中介紹過 Function 的 toString() 方法通常輸出的是函數(shù)的源代碼。
覆蓋該方法,可以返回另一個(gè)字符串(在這個(gè)例子中,返回 "Function code hidden " )。
不過, toString() 指向的原始函數(shù)怎樣了呢?它將被無用存儲單元回收程序回收,因?yàn)樗煌耆珡U棄了。
沒能夠恢復(fù)原始函數(shù)的辦法,所以在覆蓋原始方法前,存儲它的指針比較安全,以便以后的使用。
你甚至可能在某種情況下在新方法中調(diào)用原始方法:
Function.prototype.originalToString = Function.prtotype.toString;
Function.prototype.toString = function () {
if(this.originalToString().length >100) {
return "Function too leng to display."
} else {
return this.originalToString();
}  
在這段代碼中,第一行代碼把對當(dāng)前 toString() 方法的引

用保存在屬性 originalTo- String 中。然后用定制的方法覆蓋了 toString() 方法。
新方法將檢查該函數(shù)源代碼的長度是否大于 100 。
如果是,就返回錯(cuò)誤消息,說明該函數(shù)代碼太長,否則調(diào)用 originalToString() 方法,返回函數(shù)的源代碼。

根據(jù)這個(gè)例子,只要照葫蘆畫瓢寫一行
Global.prototype.parseInt = Global.prototype.parseFloat;
那么 parseInt函數(shù)真的就變成徒有其表,肚子里面干的卻是parseFloat勾當(dāng)?shù)暮瘮?shù)了。
但是,同時(shí)一個(gè)致命的問題點(diǎn)也擺在眼前。
那就是JavaScript中的Global對象,就跟神一樣, 只是個(gè)概念。
說明請參見下面《JavaScript高級程序設(shè)計(jì)》70頁關(guān)于“內(nèi)置對象”的說明。
Global對象是ECMAScript中最特別的對象,因?yàn)閷?shí)際上它根本不存在。
如果嘗試編寫下面的代碼,將得到錯(cuò)誤:
var pointer = Global;
錯(cuò)誤消息顯示Global不是對象,但剛才不是說Global是對象嗎?
沒錯(cuò)。這里需要理解的主要概念是,在ECMAScript中,不存在獨(dú)立的函數(shù),所有函數(shù)都必須是某個(gè)對象的方法。
本書前面介紹的函數(shù),如isNaN()、isFinite()、parseInt()和parseFloat()等,看起來都像獨(dú)立的函數(shù)。
實(shí)際上,它們都是Global對象的方法。

于是,上網(wǎng)大查怎樣獲取Global對象,或怎么使用Global.prototype來改變parseInt函數(shù)。
結(jié)果可想而知,神就是神,就連著名的“搜神網(wǎng)”Google也查不出來。
欲放棄之時(shí),果然應(yīng)了那句“死地而后生”。突然想到parseInt就像個(gè)全局函數(shù)一樣,根本不用什么對象調(diào)用。
那是不是說,只要把上面那句改成 parseInt = parseFloat;就可以了?
果然,神,無處不在?。?! 好用了?。?!


深度考究:
問題基本上解決了。只有一點(diǎn)需要注意的,就是JavaScript加載出錯(cuò)的時(shí)候,后面的語句就不加載執(zhí)行了。
所以這句一定要放在第一句執(zhí)行?,F(xiàn)在正好建一個(gè)JavaScript通用方法庫,要求以后每個(gè)頁面必須引入該庫文件。
所以這一句放在該JavaScript通用方法庫的第一行,從此便可高枕無憂。
但是當(dāng)我在為該段代碼寫注釋,特別是列舉如何應(yīng)用時(shí),發(fā)現(xiàn)如下代碼的問題
alert(parseInt("010", 2)); //10
alert(parseInt("010", 8)); //10
alert(parseInt("010", 10)); //10
每一個(gè)處理的返回值都是10,也就是說可以處理二進(jìn)制,八進(jìn)制,十六進(jìn)制的parseInt從此消失了。
如果說單個(gè)參數(shù)的parseInt惹出了不少麻煩,我們對于沒有惹禍的兩個(gè)參數(shù)的parseInt還是希望保留其特異功能的。
于是需要進(jìn)一步的改進(jìn)。
那么就要根據(jù)使用parseInt函數(shù)時(shí),傳遞參數(shù)的個(gè)數(shù)來進(jìn)行判斷處理。
如果只有一個(gè)參數(shù),那么就調(diào)用parseFloat返回結(jié)果。
如果有兩個(gè)以上的參數(shù),那么就調(diào)用parseInt兩個(gè)參數(shù)的處理,返回結(jié)果。
這里判斷參數(shù)個(gè)數(shù)用到arguments對象,參見《JavaScript高級程序設(shè)計(jì)》53~54頁關(guān)于arguments對象的說明。
在函數(shù)代碼中,使用特殊對象 arguments,開發(fā)者無需明確指出參數(shù)名 ,就能訪問它們。
例如,在函數(shù) sayHi() 中,第一個(gè)參數(shù)是 message。
用 arguments[0] 也可以訪問這個(gè)值,即第一個(gè)參數(shù)的值(第一個(gè)參數(shù)位于位置 0,第二個(gè)參數(shù)位于位置 1,依此類推)。
因此,無需明確命名參數(shù),就可以重寫函數(shù):
function sayHi() {
if (arguments[0] == "bye") {
return;
}
alert(arguments[0]);
}
于是就有了如下代碼:
originalparseInt = parseInt;
parseInt = function (){
if(arguments.length == 1){
return parseFloat(arguments[0]);
} else {
return originalparseInt(arguments[0], arguments[1]);
}
這段代碼里我們改造了parseInt,讓其通過參數(shù)個(gè)數(shù)的不同進(jìn)行不同的處理。
用一個(gè)新的變量originalparseInt保留了parseInt的原型。
這樣我們即便改造了parseInt,依然能通過保留的原型變量originalparseInt使用parseInt的原始功能。

返璞歸真:
代碼寫到這本以為一切都OK了,卻被人說徹底抹殺了parseInt函數(shù)對2進(jìn)制,8進(jìn)制的處理。
想想也是。處理的過于極端,只想著用parseFloat徹底替換掉討厭的parseInt函數(shù)。
如果我們正的用到2進(jìn)制或8進(jìn)制的數(shù)字轉(zhuǎn)換,還得用我們費(fèi)勁保留的parseInt函數(shù)的原型新變量originalparseInt。
其實(shí)我們的愿望很簡單。
parseInt函數(shù)中只有一個(gè)參數(shù)的時(shí)候就想讓它簡單的處理10進(jìn)制的轉(zhuǎn)換,別再因?yàn)槭孜坏?來產(chǎn)生一些頭疼的bug。
當(dāng)我們用到第二個(gè)參數(shù),想讓它處理2進(jìn)制,8進(jìn)制的時(shí)候,我還依然能用parseInt既存的功能。
于是有了下面最終的代碼:
考慮到j(luò)s文件體積的問題,盡量減少代碼量。于是把 originalparseInt 換成了 $parseInt。
另外把超級長的內(nèi)置對象名arguments直接換成了一個(gè)字母 a 這樣該對象用了4次節(jié)省的代碼量就非??捎^了。


舉一反三:
對parseInt函數(shù)的再造就完成了。
那么其實(shí)我們可以根據(jù)這次改造的經(jīng)驗(yàn),改造與parseInt具有類似的煩人特性的JavaScript方法。
譬如,escape,unescape這種已經(jīng)被 W3C組織不推薦使用的方法就可以用被推薦的方法替換掉

escape = encodeURI;
unescape = decodeURI;
那么基于這次的經(jīng)驗(yàn),今后遇到類似的問題就可以考慮到用這種乾坤大挪移的方法去解決了。

相關(guān)文章

最新評論