第二十二章 代碼重構(gòu)

以下都是一些建議,沒有哪些是必須嚴(yán)格遵守的標(biāo)準(zhǔn)瓣铣。
具體是否需要重構(gòu)答朋,以及如何進(jìn)行重構(gòu),這需要我們根據(jù)系統(tǒng)的類型坯沪、項(xiàng)目工期绿映、人力等外界因素一起決定。

22.1 提煉函數(shù)

避免出現(xiàn)過長的函數(shù),函數(shù)體內(nèi)的邏輯應(yīng)該清晰明了叉弦。

比如:

var getUserInfo = function(){
    ajax('http://xxxx', function( data ){
        console.log( 'userId:' + data.userId);
        console.log( 'userName:' + data.userName:);
        console.log( 'nickName' + data.nickName)
    }) 
}

可以重構(gòu)為:

var printDetails = function( data ){
    console.log( 'userId:' + data.userId);
    console.log( 'userName:' + data.userName:);
    console.log( 'nickName' + data.nickName);          
}

var getUserInfo = function(){
    ajax('http://xxxx', function( data ){
        printDetails( data )
    }) 
}

22.2 合并重復(fù)的條件片段

如果一個(gè)函數(shù)體內(nèi)有一些條件分支語句丐一,而這些條件分支語句內(nèi)部散步了一些重復(fù)的代碼,那么就有必要進(jìn)行合并去重工作淹冰。

var padding = function( currPage ) {
    if( currPage <= 0 ){
        currPage = 0;
        jump( currPage );   //跳轉(zhuǎn)
    } else if ( currPage >= totalPage ){
        currPage = totalPage;
        jump( currPage );   //跳轉(zhuǎn)
    } else {
        jump( currPage );   //跳轉(zhuǎn)              
    }
}

以上代碼進(jìn)行重構(gòu)后:

var padding = function( currPage ) {
    if( currPage <= 0 ){
        currPage = 0;
    } else if ( currPage >= totalPage ){
        currPage = totalPage;
    } 
    jump( currPage );   //跳轉(zhuǎn)库车,將jump函數(shù)獨(dú)立出來
}

22.3 把條件分支語句提煉成函數(shù)

在程序設(shè)計(jì)中,復(fù)雜的條件分支語句是導(dǎo)致程序難以閱讀和理解的重要原因樱拴,而且容易導(dǎo)致一個(gè)龐大的函數(shù)柠衍。
將條件分支語句提煉為一個(gè)單獨(dú)函數(shù),是一個(gè)很好的方法晶乔。

以下代碼:

var getPrice = function( price ){
    var data = new Date();
    if ( data.getMonth() >= 6 && data.getMonth() <= 9 ) {  //夏天
        return price * 0.8;
    }
    return price
}

可重構(gòu)為:

var isSummer = function() {
    var data = new Date();
    return data.getMonth() >= 6 && data.getMonth() <= 9;
}

var getPrice = function( price ){
    if ( isSummer() ) {  //夏天
        return price * 0.8;
    }
    return price
}

22.4 合理使用循環(huán)

在函數(shù)體內(nèi)珍坊,如果有些代碼實(shí)際上負(fù)責(zé)的是一些重復(fù)性的工作,那么合理利用循環(huán)不僅可以完成同樣的功能正罢,還可以使代碼量更少阵漏。

下面這個(gè)重構(gòu)代碼真好,推薦大家學(xué)習(xí):

原代碼:

var createXHR = function() {
  var xhr;
  try {
      xhr = new ActiveXObject('MSXML2.XMLHttp.6.0');
  } catch (e) {
      try{
          xhr = new ActiveXObject('MSXML2.XMLHttp.3.0');
      } catch (e) {
          xhr = new ActiveXObject('MSXML2.XMLHttp');
      }
  }
  return xhr;
}

var xhr = createXHR()

重構(gòu)之后:

var createXHR = function(){
  var versions = ['MSXML2.XMLHttp.6.0','MSXML2.XMLHttp.3.0','MSXML2.XMLHttp'];
  for(var i = 0, len = versions.length; i < len;i++ ){
       try{
          return new ActiveXObject(version) 
       } catch (e){

       }
  }
}

var xhr = createXHR() 

精彩之處在于很好的運(yùn)用for循環(huán)處理了代碼重復(fù)的問題翻具。

22.5 提前讓函數(shù)退出代替嵌套條件分支

摒棄函數(shù)只有一個(gè)出口的想法履怯,盡量減少if else語句嵌套,如果滿足條件不想再繼續(xù)執(zhí)行裆泳,請(qǐng)直接 return 退出循環(huán)叹洲。

var del = function( obj ){
  var ret;
  if( !obj.isReadOnly ){   //不為只讀的才能被刪除
      if ( obj.isFolder ) {   //如果是文件件
          ret = deleteFolder( obj )
      } else if ( obj.isFile ) {   //如果是文件
          ret = deleteFile( obj )
      }
  }
  return ret
}

上面這段代碼理解起來比較有難度,為了看到函數(shù)出口工禾,必須得讀完函數(shù)所有內(nèi)容运提,有時(shí)候,很多內(nèi)容是你不用也不想看到的帜篇。
重構(gòu)之后:

var del = function( obj ){
  if ( obj.isReadOnly ){
       return
  }
  if ( obj.isFolder ){
       return deleteFolder( obj );
  }
  if ( obj.isFile ){
       return deleteFile( obj );
  }
}

看完感覺就兩個(gè)字:清爽糙捺!

22.6 傳遞對(duì)象參數(shù)代替過長的參數(shù)列表

避免為函數(shù)傳遞過多的參數(shù),參數(shù)越多笙隙,函數(shù)就越難理解和使用洪灯。搞反參數(shù)位置也會(huì)出錯(cuò)。

最好的傳遞方式竟痰,就是把參數(shù)放進(jìn)一個(gè)對(duì)象內(nèi)签钩,然后把該對(duì)象傳遞給函數(shù)。

var obj = {
    id: 123,
    name: 'wang',
    age: 20,
    sex: '男'
}

var showInfo = function( obj ){
    console.log(obj.id);
    console.log(obj.name);
    console.log(obj.age);
    console.log(obj.sex);
}

22.7 盡量減少參數(shù)數(shù)量

如果一個(gè)函數(shù)不需要傳入任何參數(shù)就可以使用坏快,這種函數(shù)是深受人們喜愛的铅檩。

比如,現(xiàn)在有一個(gè)畫圖函數(shù) draw 莽鸿,它現(xiàn)在只能繪制正方形昧旨,接收了三個(gè)參數(shù)拾给。分別是width,height兔沃,square

var draw = function( width, height, square ){}

但實(shí)際中蒋得,square是可以通過width和height算出來的。所以上面這段代碼可以變成:

var draw = function( width, height ){
    var square = width * height;
}

所以乒疏,請(qǐng)盡量較少函數(shù)的參數(shù)额衙。

22.8 少用三目運(yùn)算符

如果條件分支邏輯簡單清晰,可以使用三目運(yùn)算符怕吴,但是如果分支邏輯非常復(fù)雜窍侧,最好不要使用三目運(yùn)算符。

三目運(yùn)算符和if else 性能一樣转绷,可是在處理復(fù)雜邏輯時(shí)候伟件,三目運(yùn)算符會(huì)損失代碼可讀性和可維護(hù)性。

22.9 合理使用鏈?zhǔn)秸{(diào)用

var user = {
    id: null,
    name: null,
    setId: function( id ) {
       this.id = id;
       return this;
    },
    setName: function( name ){
       this.name = name;
       return this;
    }
}
user.setId( 1314 ).setName( 'sven' );

22.10 分解大型類

var Spirit = function( name ){
    this.name = name;
}

Spirit.prototype.attack = function( type ) {
    if( type == 'waveBoxing' ){
        console.log( this.name + ':使用波動(dòng)拳');
    } else if ( type == 'whirlKick' ){
        console.log( this.name + ':使用旋風(fēng)腿');
    }
}

var spirit = new Spirit('RYU');

spirit.attack('waveBoxing');
spirit.attack('whirlKick');

在以上代碼中暇咆,我們可以看到 Spirit.prototype.attack 這個(gè)方法太過于龐大锋爪,實(shí)際上,它完全有必要作為一個(gè)單獨(dú)的類存在爸业。

面向?qū)ο笤O(shè)計(jì)鼓勵(lì)將行為分布在合理數(shù)量的更小對(duì)象之中。

重構(gòu)之后:

var Attack = function( spirit ){
  this.spirit = spirit;
}

Attack.prototype.start = function( type ){
  return this.list[type].call(this);
}

Attack.prototype.list = {
  waveBoxing: function(){
     console.log( this.spirit.name + ':使用波動(dòng)拳');
  },
  whirlKick: function(){
     console.log( this.spirit.name + ':使用旋風(fēng)腿');
  }
}

var Spirit = function ( name ){
  this.name = name;
  this.attackObj = new Attack( this );
}

Spirit.prototype.attack = function( type ){  //攻擊
  this.attackObj.start( type );
}

var spirit = new Spirit( 'RYU' );

spirit.attack( 'waveBoxing' );
spirit.attack( 'whirlKick' );

現(xiàn)在的Spirit精簡了很多亏镰,不再包括各種攻擊方法扯旷,而是把攻擊動(dòng)作委托給Attack類的對(duì)象來執(zhí)行。

22.11 用return退出多重循環(huán)

var func = function() {
  for( var i = 0; i < 10; i++){
       for( var j = 0; j < 10; j++ ){
            if( i * j > 30 ){
                return;
            } 
       }
  }
  console.log( i )
}
func();

以上代碼在return退出整個(gè)方法之后索抓,會(huì)導(dǎo)致 console.log(i) 沒機(jī)會(huì)執(zhí)行钧忽。

解決方案:
如果return 之后代碼比較少,可以:

var func = function() {
  for( var i = 0; i < 10; i++){
       for( var j = 0; j < 10; j++ ){
            if( i * j > 30 ){
                return i;
            } 
       }
  }
}
console.log(func())

如果代碼比較多逼肯,就可以:

var print = function( i ){
    console.log( i )
}

var func = function() {
  for( var i = 0; i < 10; i++){
       for( var j = 0; j < 10; j++ ){
            if( i * j > 30 ){
                return print(i);
            } 
       }
  }
}
func();
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末耸黑,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子篮幢,更是在濱河造成了極大的恐慌大刊,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件三椿,死亡現(xiàn)場離奇詭異缺菌,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)搜锰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門伴郁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蛋叼,你說我怎么就攤上這事焊傅〖炼福” “怎么了?”我有些...
    開封第一講書人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵狐胎,是天一觀的道長鹏倘。 經(jīng)常有香客問我,道長顽爹,這世上最難降的妖魔是什么纤泵? 我笑而不...
    開封第一講書人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮镜粤,結(jié)果婚禮上捏题,老公的妹妹穿的比我還像新娘。我一直安慰自己肉渴,他們只是感情好公荧,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著同规,像睡著了一般循狰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上券勺,一...
    開封第一講書人閱讀 49,079評(píng)論 1 285
  • 那天绪钥,我揣著相機(jī)與錄音,去河邊找鬼关炼。 笑死程腹,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的儒拂。 我是一名探鬼主播寸潦,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼社痛!你這毒婦竟也來了见转?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤蒜哀,失蹤者是張志新(化名)和其女友劉穎斩箫,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體凡怎,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡校焦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了统倒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片末购。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡吨悍,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出缴淋,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響弦追,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜花竞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一劲件、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧约急,春花似錦零远、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至奴饮,卻和暖如春纬向,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背戴卜。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來泰國打工逾条, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人叉瘩。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓膳帕,卻偏偏與公主長得像,于是被迫代替她去往敵國和親薇缅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法攒磨,類相關(guān)的語法泳桦,內(nèi)部類的語法,繼承相關(guān)的語法娩缰,異常的語法灸撰,線程的語...
    子非魚_t_閱讀 31,587評(píng)論 18 399
  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy閱讀 9,506評(píng)論 1 51
  • 說到茶道浮毯,我是個(gè)地地道道的門外漢,也是在紅菇的影響下泰鸡,第一次接觸了茶文化债蓝,第一次了解了紅茶的故事,感觸頗深盛龄。 人們...
    林星兒閱讀 391評(píng)論 0 4
  • 有的時(shí)候锹淌,你看一部電視劇或者電影,也許只為了看到那一句話而已罷了赠制。關(guān)于電影里的劇情和人物你可能早已經(jīng)忘記赂摆。但是那句...
    鄧小怪閱讀 447評(píng)論 0 0
  • 二十歲的你烟号,能干什么?二十歲的你或許在上大學(xué)厘唾,每天睡覺學(xué)習(xí)玩手機(jī)褥符?二十歲我們充滿稚嫩但又初步接觸到這個(gè)社會(huì)的煙塵之...
    柒89閱讀 326評(píng)論 0 0