從javascript語言本身談項目實戰(zhàn)

??????
隨著ajax的升溫,javascript越來越得到人們的重視。重要的是,ajax在一定程度上帶來了web軟件架構(gòu)上的變化,人們把越來越多的功能分
配到客戶端實現(xiàn),javascript子項目規(guī)模越來越大。如何更高效的使用javascript,如何更科學(xué)的組織javascript,如何更順利的
保證項目進(jìn)展?我想就我的經(jīng)驗談一點淺見。



一。 開發(fā)人員需要認(rèn)真學(xué)習(xí)javascript語言本身
?????? 由于javascript是“世界上最被誤解的語言”,
大部分人對javascript語法并沒有全面了解過,只是憑借看起來很像c或者java的關(guān)鍵字按照自己的理解寫javascript代碼。其實
javascript是一種很獨特的語言,和c++/java有非常大的區(qū)別,要想用javascript做大一些的項目,開發(fā)人員必須老老實實的學(xué)習(xí)
javascript的語法。真正掌握了語法后,我們才不會把delete看成釋放內(nèi)存對象,才不會為到底參數(shù)傳遞是值傳遞還是引用傳遞而煩惱。真正理解
了javascript的基于原型的OO方式,才可能寫出具有良好架構(gòu)的javascript程序。
??????
《javascript權(quán)威指南》是一本最合適的書,鄭重推薦。另外ECMA262
文檔可以作為參考。網(wǎng)上流行的jscript手冊chm版本使用起來比較方便,不過這是微軟的jscript實現(xiàn),和標(biāo)準(zhǔn)的javascript略有區(qū)別,使用時應(yīng)該注意上面的注腳信息。關(guān)于javascript的原型和OO,網(wǎng)上已經(jīng)有很多文章介紹了,在此不再多說。



二。 良好的代碼來源于良好的設(shè)計
??????
只有設(shè)計優(yōu)良,代碼才會寫的漂亮。現(xiàn)在的javascript子項目已經(jīng)不是以前web項目中的“邊角料”和散兵游勇了,在較大的ajax項目內(nèi),
javascript將非常復(fù)雜,ajax的異步模型也和以前順序執(zhí)行的程序設(shè)計有所區(qū)別。所以建議做javascript前首先做好設(shè)計。推薦使用用例
驅(qū)動的方式,把用例分析清楚,以便全局考慮所有可能的頁面交互過程,繪出頁面內(nèi)一些對象之間的交互圖,分析一些數(shù)據(jù)對象的狀態(tài),作出精細(xì)的
javascript設(shè)計。


三。 使用設(shè)計模式,復(fù)用其他領(lǐng)域的設(shè)計經(jīng)驗

???????
如果javascript非常復(fù)雜,可以考慮使用一些模式。我想大部分做javascript的開發(fā)者都不是“javascript科班”出身吧:)
掌握了javascript的語言本質(zhì),就可以復(fù)用我們在其他領(lǐng)域的經(jīng)驗了。使用javascript框架或者ajax框架,使用單例模式做一個全局的數(shù)
據(jù)緩沖池,或者使用觀察者模式把界面對象和數(shù)據(jù)對象分離,使用命令模式實現(xiàn)用戶的操作隊列等等。


四。 調(diào)試代碼的技巧

??????? javascript的代碼不太好調(diào)試,這是由于:


  • 一般的開發(fā)人員對javascript語言本身不太精通。也就是上面提到的。
  • web項目包含較多的因素,復(fù)雜性加劇。服務(wù)端腳本、模板、html、js等很多環(huán)節(jié)都可能增加調(diào)試難度。
  • 瀏覽器存在兼容性問題。有可能在一個細(xì)節(jié)問題上IE、Mozilla、opera等瀏覽器都有差異。
  • 工具的缺乏。雖然mozilla的jsdebugger非常好用(還有bug,比如eval時調(diào)試器有些問題),但是其他瀏覽器環(huán)境下調(diào)試工
    具就不怎么樣了。ms系統(tǒng)自帶的script
    debug工具調(diào)試本地代碼還可以,直接調(diào)試網(wǎng)站js代碼表現(xiàn)欠佳。opera除了javascript控制臺外我沒有找到其他調(diào)試工具。

?????? 在此我推薦幾個調(diào)試技巧:

  1. 使用Mozilla firefox的jsdebugger插件。這個我不再多說了,最經(jīng)典的js調(diào)試工具。在線調(diào)試遠(yuǎn)程站點的javascript效果非常棒。
  2. 把問題隔離,建立本地的html文件和js文件,使用ms script debug調(diào)試工具來調(diào)試。如果js模塊比較獨立,可以使用這個工具的。如果寫hta的項目,這個工具當(dāng)然是首選了。
  3. httpWatch 這是一個ie下的插件,非常好用,能夠監(jiān)視ie中的任何http會話,并能夠看到http會話的原文。可以通過這個工具了解你的程序有沒有和服務(wù)器產(chǎn)生會話,參數(shù)&返回的數(shù)據(jù)到底是什么。

    ?
  4. 在網(wǎng)頁內(nèi)建立用于調(diào)試的textarea

    可以在網(wǎng)頁內(nèi)建立一個textarea來接受你想運行的js語句,然后加一個按鈕使用js的eval函數(shù)執(zhí)行你輸入的代碼。

    這種方式非常適合在線調(diào)試,網(wǎng)頁出錯后寫代碼輸出頁面內(nèi)的對象值。建議寫一些dump工具函數(shù)配合使用,效果更佳。

    我非常喜歡這種方式,可以隨時使用開關(guān)打開頁面內(nèi)隱藏的textarea進(jìn)行調(diào)試,感覺很像給一臺服務(wù)器接上了終端,然后使用shell可以做任何事情:) 函數(shù)可以在這里重新定義,可以任意操作界面中的任何元素,調(diào)用任何對象的任何函數(shù),輸出任何你需要的運行時刻值。

    ?
  5. 使用異常(exception)和斷言(assert)

    使用try{}catch(e){}結(jié)構(gòu)不光可以屏蔽出錯信息,讓界面更友好。我們的程序可以使用異常、拋出異常來構(gòu)建一種更好的出錯處理機制。

    有這樣一個故事,我在使用string.localeCompare函數(shù)時隨手寫了這樣的代碼:

    var iRe = str1.localeCompare(str2);

    switch(iRe){

    0: return ....

    1: return ....

    -1:return ....

    defalut:throw "error:localeCompare return other value"

    }

    寫完就忘了,沒想到我的同事在linux下使用firefox時,異常被拋出了,然后我們得知:linux firefox下localeCompare返回的不只是0/1/-1,而是返回一個具體值.

    這個異常拋出有效的檢測出了代碼的不完美。

    ???

    firefox下的異常dump后能得到較為詳細(xì)的調(diào)用棧信息,這一點非常好。IE的異常信息沒有這么詳細(xì)。

    ???

    異常和斷言也可以結(jié)合成為一個非常有效的調(diào)試工具。

    斷言(assert)是在其他語言中的一種很有效的調(diào)試工具,常常以這種形式出現(xiàn):

    assert(<條件>);

    在程序處于debug狀態(tài),當(dāng)條件為假時,系統(tǒng)中止運行并報告這個斷言。由于斷言是我們自己定義的,所以我們可以很容易的判斷出出錯的地方,進(jìn)而找到bug所在。

    javascript語言沒有提供宏,也沒有提供assert,我們可以這樣模擬

    if(_is_debug) assert = function(expression , strLable){

    ??? if( !expression ) throw Error(strLable);

    }

    else assert = function(){};//_is_debug是一個全局變量

    這樣可以實現(xiàn)在發(fā)生"不可能的事情"的時候,讓程序在調(diào)試模式下拋出異常,在發(fā)布版本中不作理會。

    ???

    ??? 可以這樣輸出當(dāng)前棧的調(diào)用信息,彌補剛才提到的IE中異常對象沒有棧信息的缺陷:

    function callStackInfo(){

    ???
    var s="",line="";

    var cer=arguments.callee.caller;

    while(cer){

    var sf=cer.toString();

    s+=line+sf.substring(sf.indexOf('function'),sf.indexOf('{'))+"\n";

    line=".."+line;

    cer=cer.caller;

    }

    return s;

    }

??????
本文只就javascript在web開發(fā),特別是在ajax方面的開發(fā)做了一些討論,主要在于管窺如何更好的使用“純javascript”。web開
發(fā)還有很多其他方面,比如xml和Dom等實際上和javascript息息相關(guān),但是本文沒有涉及,還請見諒。歡迎各位朋友就我的討論多提意見。