日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
JavaScript重構(gòu)深入剖析

通常我們的團隊中,開發(fā)人員在Java語言層面具備相當?shù)募夹g(shù)素養(yǎng),經(jīng)驗豐富,而且有許多成熟的、合理的規(guī)約,類型繁多的代碼隱患檢查工具,甚至在團隊間還有計劃內(nèi)的評審和飛檢。但是前端的代碼不似后臺,就像一個沒人疼的孩子,不僅僅容易被低估、被輕視,導致質(zhì)量低劣、可維護性差,技能上,更缺少優(yōu)秀的前端開發(fā)人員。

成都創(chuàng)新互聯(lián)長期為上千客戶提供的網(wǎng)站建設(shè)服務(wù),團隊從業(yè)經(jīng)驗10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為玉州企業(yè)提供專業(yè)的做網(wǎng)站、成都網(wǎng)站設(shè)計,玉州網(wǎng)站改版等技術(shù)服務(wù)。擁有10余年豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。

JavaScript是前臺代碼中重要組成部分,隨著版本的延續(xù),產(chǎn)品越做越大,JavaScript層面的重構(gòu),需要在整個過程中逐步強化起來。

當代碼量達到一定程度,JavaScript最好能夠與頁面模塊組件(例如自定義的FreeMarker標簽)一起被模塊化。

模塊化帶來的最大好處就是獨立性和可維護性,不用在海量的js中定位問題位置,簡單了,也就更容易被理解和接受,更容易被定制。

模塊之間的依賴關(guān)系最好能夠保持簡單,例如有一個common.js,成為最通用的函數(shù)型代碼,不包含或者包含統(tǒng)一管理的全局變量,要求其可以獨立發(fā)布,其他組件js可以輕松地依賴于它。舉個例子,我們經(jīng)常需要對字符串實現(xiàn)一個trim方法,可是js本身是不具備的,那么就可以在這個common.js中擴展string的prototype來實現(xiàn),這對外部的使用者是透明的。

模塊劃分和命名空間

使用命名空間是保持js互不干擾的一個好辦法,js講究起面向?qū)ο?,就必須遵循封裝、繼承和多態(tài)的原則。

參照Java import的用法,我希望命名空間能帶來這樣的效果,看一個最簡單的實例吧:

我有一個模塊play,其中包含了一個方法webOnlinePlay,那么在沒有import這個模塊的時候,我希望是js的執(zhí)行是錯誤的:

 
 
 
 
  1. webOnlinePlay(); //Error! 無法找到方法 

但是如果我引入了這個模塊:

 
 
 
 
  1. import("play");  
  2. webOnlinePlay(); //正確,能夠找到方法  

其實實現(xiàn)這樣的效果也很簡單,因為默認調(diào)用一個方法webOnlinePlay()的實質(zhì)是:window.webOnlinePlay(),對嗎?

所以在import("play")的時候,內(nèi)部實現(xiàn)機制如下:

 
 
 
 
  1. var module = new playModule(); 

對于這個模塊中的每一個方法,都導入到window對象上面,以直接使用:

 
 
 
 
  1. window[methodName] = module[methodName]; 

其實這里并沒有什么玄機,但是這種即需即取的思想?yún)s給前端重構(gòu)帶來了一個思路,一個封裝帶來的可維護性增強的思路,不是嗎?

聰明的你也許還會提到一個問題:

如果我沒有import這個play模塊,這個頁面都不需要,那我能否連這個play.js都不加載呢?

當然可以,請關(guān)注下一頁———關(guān)于js的動態(tài)加載的部分。

#p#

JavaScript的動態(tài)加載

前一節(jié)留下了一個問題,如果JS分門別類也清晰了,那我現(xiàn)在需要在必要的情況下才加載某一模塊的JS,這個怎么實現(xiàn)呢?

方法一,最簡單也是最容易被接受的方法,通過后臺代碼來控制,還是少些復(fù)雜的JS吧,通過一個標簽、一個分支判斷,就可以做到,何樂而不為呢?

方法二,如果要使用純JS來控制,那么看看這樣如何:

 
 
 
 
  1. $.ajax(){   
  2.     url:"xxx/play.js";   
  3.     ……   
  4.     success:function(res){   
  5.         eval(res.responseText);   
  6.     }   

原理是很簡單,不過有一個藏匿著的魔鬼:eval,js加載的生效就靠它了,那么執(zhí)行的上下文就在它的里面,這就會帶來一些潛在的問題,而且,調(diào)試也變得困難。

方法三,通過添加   

  •  //模塊JS  
  •  
  •     function testWithMainProcess() {   
  •         assertEquals("Web play url""##http://...##", webOnlinePlay());   
  •     } 
  • 項目的代碼里到處是Ajax調(diào)用,要做單元測試,看來打樁是不可避免了。Mock類的工具有許多,比如適合JQuery的QMock:

     
     
     
     
    1. var mockJquery = new Mock();   
    2.    mockJquery   
    3.       .expects(1)   
    4.       .method('ajax')   
    5.       .withArguments({   
    6.          url: 'http://xxx,   
    7.          success: Function,   
    8.          dataType: "jsonp"   
    9.       })   
    10.       .callFunctionWith({ feed : { entry : "data response" }}); 

    這個樁正是mock了一個假的ajax jason返回:[feed:[entry:"data response"]],看看,使用就和以前接觸過的EasyMock差不多嘛。

    對于JavaScript測試框架感興趣的同學還可以了解一些其他的測試框架,例如JSpec。

    單元測試代碼建議就放在模塊的包內(nèi):test.html,即便理想狀況下,模塊單獨發(fā)布時,也是伴隨著測試用例的可靠的前端代碼。

    從哪些JavaScript代碼開始做?

    1、函數(shù)式的代碼。這樣的代碼保證獨立性好,也不需要打什么樁,測試成本低,如果不明白函數(shù)式的代碼的含義,請參見“函數(shù)式編程”。

    2、復(fù)雜的邏輯。

    是否嘗試TDD?不建議在我們團隊內(nèi)部使用,前端TDD需要更高的技巧,對人的因素要求更高。如果有一天,后臺Java代碼的TDD做好了,那么換成JavaScript的代碼,沒有本質(zhì)區(qū)別。

    如果效果得當,為什么不能把JavaScript的UT集成到ICP-CI上作為持續(xù)集成的一部分呢?

    #p#

    JavaScript編碼規(guī)則

    沒有規(guī)矩,不成方圓,JavaScript帶來了靈活性,也帶來了不受控的變量和訪問,所以要用規(guī)則限制它。一支成熟的團隊,還是一支新鮮的團隊,規(guī)則應(yīng)當是不一樣的,我只是列出一些常見的或者有效的辦法,來約束跳躍的開發(fā)人員,思維可以任意飛躍,代碼卻要持續(xù)受控。當然,任何規(guī)則都是建立在一定的認知基礎(chǔ)之上的,面向?qū)ο驤avaScript的基礎(chǔ)是必備的,否則一切無從談起。

    變量和方法控制:

    模塊開發(fā)不允許存放獨立的全局變量、全局方法,只允許把變量和方法放置到相應(yīng)模塊的“命名空間”中,對此的解釋請參見此文。實在心癢了,那么使用匿名函數(shù)如何?

      
      
      
      
    1. (function() {   
    2.     var value = 'xxx';   
    3.     var func = function() {...};   
    4. })(); 

     

    模塊化需要嚴格控制住代碼的區(qū)域性,這不僅僅是代碼可維護性、可定制性的一方面,同時也讓JavaScript引擎在屬性和方法使用完畢后及時地回收掉。

    不允許在模塊代碼中污染原生對象,例如

      
      
      
      
    1. String.prototype.func = new function(){...}; 

    如此的代碼必須集中控制,例如統(tǒng)一放置在common.js中,嚴格保護起來。

    數(shù)據(jù)存放約束:

    普通變量、prototype變量和function變量分而治之,方法名一律大寫開頭,變量名還是遵從駱駝命名法如何:

      
      
      
      
    1. function T(name){   
    2.     T.prototype._instance_number++;   
    3.     this.name = name;   
    4.     this.showName=function(){   
    5.         alert(this.name);   
    6.     }   
    7. };   
    8. T.prototype = {   
    9.     _instance_number:0,    
    10.     getInstanceNum: function(){    
    11.         return T.prototype._instance_number;   
    12.     }   
    13. };  
    14.  
    15. var t = new T("PortalONE");   
    16. t.showName();   
    17. new T("Again");   
    18. alert(t.getInstanceNum()); //打?。? 

     

    這里有意做了一件事情,T內(nèi)部的屬性和私有方法使用下劃線開頭,這樣很好地實現(xiàn)了封裝(上述代碼中如果使用t.instanceNum,是無法訪問到這個值的),如果這段代碼都看不懂的話,趕緊溫習一下JavaScript的面向?qū)ο蟀?:)。JavaScript中提供了閉包和原型兩種辦法來實現(xiàn)繼承和多態(tài),關(guān)于重構(gòu)中應(yīng)用這一點,后續(xù)的章節(jié)我再啰嗦吧。

    另外,優(yōu)先使用JavaScript的原生對象和容器,比如Array,Ajax的數(shù)據(jù)類型統(tǒng)一切到JSON上來,盡量不要使用隱藏域;另外,通常是不允許隨意擴展DOM對象的。

    至于模塊間的通信:模塊間的通信意味著模塊間的耦合性,是需要嚴格避免的;通信的途徑通常使用方法級屬性或者模塊級的prototype變量。

    DOM操縱規(guī)則:

    在模塊代碼中,通常要求把對DOM的操縱獨立到模塊js中,應(yīng)當避免在DOM模型上顯示地寫時間觸發(fā)函數(shù),例如:

      
      
      
      
    1.  onclick="xxx" /> 

    借助JQuery基于bind的一系列方法,把行為邏輯獨立出來以后,完全可以看到清爽的HTML標簽。

    DOM對象的訪問通常使用id來查找,偶有根據(jù)name來查找的,過多次數(shù)地、不合理地遍歷DOM樹是前端性能保持的大忌。

    CSS的樣式控制:

    (1)盡量拒絕style="xxx"的寫法,主要目的是將樣式統(tǒng)一到主題樣式表單中,當然主題樣式表單也是按模塊存放的,對于不同語種的定制和不同風格的切換帶來便利。

    (2)規(guī)約JavaScript對樣式的操縱,理想狀況下,封裝性好的UI可以自由地替換它的樣式集合。

    以上只能算冰山一角,拋磚引玉,實際項目中需要在開發(fā)過程中逐步細化和完善。

    #p#

    利用原型和閉包,完成組件方法

    終于要定義一個組件方法了,利用原型來實現(xiàn)??纯催@樣如何:

      
      
      
      
    1. function Player(name){   
    2.     Player.MIN_EXTENDED_TIME = 1;   
    3.     Player.MAX_EXTENDED_TIME = 3;   
    4.     this._name = name;   
    5. };   
    6. Player.prototype.setName = function(name){   
    7.     this._name = name;   
    8. };   
    9. Player.prototype.toString = function(){   
    10.     return "Player: " + this._name;   
    11. };  
    12.  
    13. var player = new Player("WindowsMediaPlayer");   
    14. alert(player.toString()); //輸出WindowsMediaPlayer   
    15. player.setName("RealPlayer");   
    16. alert(player.toString()); //輸出RealPlayer   
    17. alert(Player.MAX_EXTENDED_TIME); 

    恩,有封裝、有常量、也有復(fù)寫了Object的toString方法,至于繼承之類的事情,咱們后面再說,初看看還不錯??墒沁@樣的組件方法定義不夠優(yōu)雅,也不夠直觀,方法都是放在獨立的位置定義的,并沒有和最開始的組件方法放置在一起,如果能像Java那樣定義豈不更好?

    對了,可以用閉包來實現(xiàn)。試試看吧:

      
      
      
      
    1. function Player(name){   
    2.     Player.MIN_EXTENDED_TIME = 1;   
    3.     Player.MAX_EXTENDED_TIME = 3;   
    4.     this._name = name;   
    5.     this.setName = function(name){   
    6.         this._name = name;   
    7.     };   
    8.     this.toString = function(){   
    9.         return "Player: " + this._name;   
    10.     };   
    11. };  
    12.  
    13. var player = new Player("WindowsMediaPlayer");   
    14. alert(player.toString()); //輸出WindowsMediaPlayer   
    15. player.setName("RealPlayer");   
    16. alert(player.toString()); //輸出RealPlayer   
    17. alert(Player.MAX_EXTENDED_TIME); 

     

    不像Groovy里面,閉包做了很大程度上的強化,包括新的語法的支持;JavaScript的閉包是很簡單的閉包,它沒有特殊的需要額外學習的語法,任意一個function,里面只要包含未綁定變量,這些變量是在function所屬的上下文環(huán)境中定義的,那么,這個function就是閉包。順便羅嗦一句,和閉包相反的,不正是不包含任何未綁定變量的函數(shù)式代碼嗎?

    寫是寫好了,可是轉(zhuǎn)念一想,Player應(yīng)當只有一份,它是單例的,最好我也能像Java那樣弄一個單例模式出來 :),可是事不遂愿,我沒有辦法在JavaScript做一個private的構(gòu)造器,用這種思路去實現(xiàn)單例模式似乎不可行……

    怎么辦?

    然而天無絕人之路,我控制不了你new一個Player的對象,我卻可以控制你new出來的這個Player對象的屬性和行為!當你需要使用你new出來的Player的對象的時候,你發(fā)現(xiàn)根本無法完成,或者它只是一個空殼!真正的東西還是要靠單例中經(jīng)典的getInstance方法來獲得:

      
      
      
      
    1. function Player(){   
    2.     throw new Error("Can not instantiate a Player object.");   
    3. }; //這只是個空殼  
    4.  
    5. (function(){ //這才是貨真價實的東西   
    6.     Player.MIN_EXTENDED_TIME = 1;   
    7.     Player.MAX_EXTENDED_TIME = 3;   
    8.     Player._player = false;   
    9.     Player.getInstance = function(){   
    10.         if(!Player._player){   
    11.             alert("Init...");   
    12.             Player._player = {   
    13.                 _name : name,   
    14.                 setName : function(name){   
    15.                     this._name = name;   
    16.                 },   
    17.                 toString : function(name){   
    18.                     return "Player: " + this._name;   
    19.                 }   
    20.             };   
    21.         }   
    22.         return Player._player;   
    23.     };   
    24. })();  
    25.  
    26. //var player = new Player(); //new Player()會拋出異常   
    27. var player1 = Player.getInstance();   
    28. var player2 = Player.getInstance();   
    29. player2.setName("RealPlayer");   
    30. alert(player2.toString()); //輸出RealPlayer 

     

    好,真不錯,單例模式在JavaScript下也成功實施了——你要膽敢new Player();就會拋出一個異常,這樣什么也得不到,只有用getInstance方法得到的對象才是真真正正的Player對象。上面的代碼整個執(zhí)行的結(jié)果,只彈出了一次"Init..."的對話框,說明真正的“構(gòu)造器邏輯”只調(diào)用了一次。

    都做到這份上了,依然有小小的遺憾,Player的定義依然被拆分成了兩部分,一部分定義空殼,一部分是一個匿名函數(shù)來定義Player的常量和getInstance方法。這兩部分就不能合二為一么?

    能。只需要用到一個小小的匿名函數(shù),如果耐心從頭看到這里,也一定能理解:

      
      
      
      
    1. var Player = (function(){   
    2.     Player = function(){ //這只是個空殼   
    3.         throw new Error("Can not instantiate a Player object.");   
    4.     };   
    5.     Player.MIN_EXTENDED_TIME = 1;   
    6.     Player.MAX_EXTENDED_TIME = 3;   
    7.     Player._player = false;   
    8.     Player.getInstance = function(){   
    9.         if(!Player._player){   
    10.             alert("Init...");   
    11.             Player._player = {   
    12.                 _name : name,   
    13.                 setName : function(name){   
    14.                     this._name = name;   
    15.                 },   
    16.                 toString : function(name){   
    17.                     return "Player: " + this._name;   
    18.                 }   
    19.             };   
    20.         }   
    21.         return Player._player;   
    22.     };   
    23.     return Player; //把修繕完工的Player這個組件方法返回   
    24. })();  
    25.  
    26. //var player = new Player(); //new Player()會拋出異常   
    27. var player1 = Player.getInstance();   
    28. var player2 = Player.getInstance();   
    29. player2.setName("RealPlayer");   
    30. alert(player2.toString()); //輸出RealPlayer 

     

    到此,終于如釋重負,深入理解JavaScript面向?qū)ο?,用好原型和閉包這兩把鋒利的武器,才能寫出優(yōu)秀的前端代碼來。

    #p#

    利用繼承來做事

    終于要說到JavaScript的繼承了,原型鏈繼承是最常用的一種方式:

      
      
      
      
    1. function Video(){};   
    2. function Movie(){};   
    3. Movie.prototype = new Video();   
    4. Movie.prototype.constructor = Movie; //不要丟失構(gòu)造器 

    啰嗦一句,如果我拿到的是方法的實例,一樣可以做繼承:

      
      
      
      
    1. function Video(){};   
    2. function Movie(){};   
    3.  
    4. var video = new Video();   
    5. video.size = 3;   
    6. video.toString = function(){   
    7.     return "video";   
    8. };   
    9. video.getName = function(){   
    10.     return "VideoXXX";   
    11. };   
    12. var movie = new Movie();   
    13. (function inherit(parent,child){   
    14.     for(var ele in parent){   
    15.         if(!child[ele]) //在child不包含該屬性或者方法的時候,才會拷貝parent的一份   
    16.             child[ele] = parent[ele];              
    17.     }   
    18. })(video,movie); //匿名函數(shù)調(diào)用的方式    
    19.     
    20. alert(movie.size); //3   
    21. alert(movie.toString()); //[object Object]   
    22. alert(movie.getName()); //VideoXXX 

    可是這種方法是不純粹繼承的,可見其中的toString方法由于是原生方法,無法用var ele in parent遍歷到的。

    如果僅僅想覆寫父類的某個方法,還可以使用call或者apply嘗試一下方法的this大挪移,略。

    原型鏈繼承看起來似乎是最自然和最具親和力的繼承方式了,但是還記得上一節(jié)中對于單例模式的處理嗎?我使用了getInstance方法去取得一個唯一的實例,而不是new,這樣原型對其實例化起不到作用了:

      
      
      
      
    1. var Player = (function(){   
    2.     Player = function(){ //這只是個空殼   
    3.         throw new Error("Can not instantiate a Player object.");   
    4.     };   
    5.     Player.MIN_EXTENDED_TIME = 1;   
    6.     Player.MAX_EXTENDED_TIME = 3;   
    7.     Player._player = false;   
    8.     Player.getInstance = function(){   
    9.         if(!Player._player){   
    10.             alert("Init...");   
    11.             Player._player = {   
    12.                 _name : name,   
    13.                 setName : function(name){   
    14.                     this._name = name;   
    15.                 },   
    16.                 toString : function(name){   
    17.                     return "Player: " + this._name;   
    18.                 }   
    19.             };   
    20.         }   
    21.         return Player._player;   
    22.     };   
    23.     return Player; //把修繕完工的Player這個組件方法返回   
    24. })(); 

    現(xiàn)在,我要創(chuàng)建一個WindowsMediaPlayer,去繼承上面的Player,怎么做?

    這里提供兩條思路:

    (1)獲取Player的實例,然后遍歷實例中的方法和屬性,構(gòu)造一個全新的WindowsMediaPlayer,其它的屬性照抄Player,但是唯有g(shù)etInstance方法需要覆寫。這個方式不夠優(yōu)雅,而且getInstance方法可能會很復(fù)雜和冗余,也許不是一個很好的思路。

    (2)從對象設(shè)計的角度來說,一個單例的類,本身就不適合被繼承,那么,還不如把Player做成一個純粹的抽象層,讓單例這個工作交給其子類WindowMediaPlayer去完成。這個方式要好得多,至于如何把一個function做成一個抽象層。

    #p#

    重用老代碼

    在Java中,有這樣一段老代碼:

      
      
      
      
    1. class Round{   
    2.     public void drawRound(); //畫圓   

    現(xiàn)在新代碼希望能和它共存,使用一個Person的對象來控制,只不過,可能drawRound,也可能drawRect?。?/p>

      
      
      
      
    1. class Rect{   
    2.     public void drawRect(); //畫方   

    好,廢話少說,我先想到了Adapter模式:

      
      
      
      
    1. interface Drawable{   
    2.     public void draw();   
    3. }  
    4.  
    5. public class RoundAdapter implements Drawable{   
    6.     private Round round;   
    7.     public void draw(){   
    8.         round.drawRound();   
    9.     }   
    10. }  
    11.  
    12. public class RectAdapter implements Drawable{   
    13.     private Rect rect;   
    14.     public void draw(){   
    15.         rect.drawRect();   
    16.     }   

    然后,我再引入一個Person對象,就能搞定這一切了:

      
      
      
      
    1. class Person{   
    2.     private Drawable adapter;   
    3.     public Person(Drawable adapter){   
    4.         this.adapter = adapter;   
    5.     }   
    6.     public void draw(){   
    7.         this.adapter.draw();   
    8.     }   
    9. }  
    10.  
    11. Drawable rou = new RoundAdapter();   
    12. Drawable rec = new RectAdapter();   
    13. new Person(rou).draw(); //畫圓   
    14. new Person(rec).draw(); //畫方 

    想必到此已經(jīng)讓你煩了,一個Adapter模式的最簡單例子。再多看一看,這個模式的核心是什么?接口!對,正是例子中的Drawable接口——正是在接口的規(guī)約和領(lǐng)導下,我們才能讓畫圓和畫方都變得那么聽話。

    現(xiàn)在JavaScript中,也有這樣一段老代碼:

      
      
      
      
    1. function Round(){   
    2.     this.drawRound = function(){   
    3.         alert("round");   
    4.     }   

     

    我也想依葫蘆畫瓢,但是JavaScript沒有接口了,怎么辦?

    ……

    接口的作用是什么?是對類的行為的規(guī)約,可是JavaScript的行為是動態(tài)的,無法用簡單純粹的接口來實現(xiàn)、來約束,即便模擬出這樣一個接口(參見《JavaScript Design Pattern》),在此又有必要使用它么?強行做出一個接口來,這不是和JavaScript的初衷相違背了嗎?

    再回到這個問題上面,我原本希望Person的對象可以調(diào)用一個統(tǒng)一的draw方法,只是在通過構(gòu)造Person對象的時候,傳入一個不同實現(xiàn)的Drawable對象,做出了不同約束下的實現(xiàn)。

    那么,JavaScript中,不僅僅方法的調(diào)用者可以作為一個參數(shù)傳入,方法本身也可以作為參數(shù)傳入(即所謂方法閉包),這樣,所有變化點都控制在這個參數(shù)之中,不也實現(xiàn)了我想要的接口規(guī)約的效果嗎:

      
      
      
      
    1. function Rect(){   
    2.     this.drawRect = function(){   
    3.         alert("rect");   
    4.     }   
    5. }  
    6.  
    7. function Person(obj){   
    8.     //obj參數(shù)的格式:{doWhat,who}   
    9.     for(var i in obj){   
    10.         this.doWhat = i;   
    11.         this.who = obj[i];   
    12.         break;   
    13.     }   
    14.     this.draw = function(){   
    15.         this.who[this.doWhat].call(this.who);   
    16.     };   
    17. }  
    18.  
    19. var rou = { drawRound : new Round() };   
    20. var rec = { drawRect : new Rect() };   
    21. (new Person(rou)).draw();   
    22. (new Person(rec)).draw();  
    23.  
    24.   

     

    寫到這里,我覺得很開心:

    在Java中,通過接口的規(guī)約和適配器的幫助,我將變化點封裝在Person構(gòu)造器的參數(shù)之中;

    JavaScript中,沒有了接口、脫離了適配器的幫助,我依然能將變化點封裝在Person的構(gòu)造器參數(shù)之中。

    #p#

    JSDoc和JSLint

    JSDoc可以生成類似于JavaDoc一樣的API文檔,這對于前端開發(fā)是必不可少的。

    下載jsdoc-tookit(http://code.google.com/p/jsdoc-toolkit/)和jsdoc-tookit-ant-task(http://code.google.com/p/jsdoc-toolkit-ant-task/)

      
      
      
      
    1. default="build-docs">   
    2.      "build-docs">   
    3.          "base" location="." />   
    4.          "jsdoctoolkit" classname="uk.co.darrenhurley.ant.tasks.JsDocToolkit" classpath="jsdoc-toolkit-ant-task-1.1.0.jar;jsdoc-toolkit\java\classes\js.jar"/>   
    5.          "jsdoc" jsdochome="${base}/jsdoc-toolkit/" outputdir="${base}/output/">   
    6.              "portalone-common.js" />   
    7.            
    8.        
    9.  

    其它也有類似的工具,DOC生成器對于任何一個成熟的前端開發(fā)團隊都是必不可少的。

    JSLint是用來對JavaScript代碼做靜態(tài)檢查的工具(http://jslint.com/),不過這個應(yīng)該不是開源的;而且需要ruby運行環(huán)境和gvim,再配合cscript engine,使用起來有諸多不便。項目中不可能總使用在線版本:

    Eclipse上也開發(fā)了相應(yīng)的JSLint plugin,另外,有一個很方便的工具jslint-toolkit(http://code.google.com/p/jslint-toolkit/):

    先配置config.json,紅色字體就是要檢查的js目錄:

      
      
      
      
    1. {   
    2.     // JavaScript files to check   
    3.     //"includes": ["scripts\\source", "scripts\\jquery"],   
    4.     "includes": ["scripts\\my"],   
    5.     // Exclude files   
    6.     "excludes": [],   
    7.     // Exclude file names (Regex expression)   
    8.     "excludeNames": ["\\.svn", "CVS"],   
    9.     // Output directory   
    10.     "outPath": "out"   

     

    輸出結(jié)果一目了然:

    原文鏈接:http://blog.csdn.net/RayChase/archive/2011/05/15/6423039.aspx


    文章名稱:JavaScript重構(gòu)深入剖析
    瀏覽路徑:http://www.5511xx.com/article/dhhdjpi.html