js的設計模式是針對於總體代碼的設計是否合理,給出了一些具體的解決辦法。 而重構代碼就是依賴於設計模式而實現的一個必要手段,能夠說設計模式就是重構代碼的目標,但他的手段卻不只僅只有設計模式這些大而全的,一樣存在小而精,咱們隨處可使用的。css
咱們一般在寫代碼的時候,一開始,並不須要考慮太多。在後期能夠進行修改和提煉。 好比,我有個業務需求,是建立一個div而且渲染數據到頁面上,而且根據data的不一樣,改變div的狀態.設計模式
function(data){ var div = document.createElement("div"), div.innerHTML = data.name; document.body.append(div); if(data.isShow){ div.style.display = "block"; }else{ div.style.display = "none"; } }
但事實上,這個函數裏面還有一個代碼塊,就是根據data.isShow改變div的狀態.咱們能夠對其進行封裝。app
function(data){ var div = document.createElement("div"), div.innerHTML = data.name; document.body.append(div); changeState(data.isShow,div); } function changeState(flag,div){ div.style.display = flag?"block":"none"; }
這裏主要針對於,屢次重複調用同一個封裝代碼塊函數。ide
function(flag){ if(flag==="left"){ move("right"); }else if(flag==="right"){ move("left"); }else if(flag==="top"){ move("bottom"); }else if(flag==="bottom"){ move("top"); } }
根據flag向反方向移動,能夠看出,裏面都有用到了move()這個方法,要知道,分支語句是最不利於程序閱讀的,並且咱們要儘量的減小和簡化分支語句裏面的程序量,讓閱讀者耗費在分支語句上的時間降到最少。上面代碼能夠這樣寫。函數
function(flag){ var dir; if(flag==="left"){ dir = "right"; }else if(flag==="right"){ dir = "left"; }else if(flag==="top"){ dir = "bottom"; }else if(flag==="bottom"){ dir = "top"; } move(dir); }
恩,固然,這樣寫也是違反人性的。咱們可使用命令模式進行重構。
這就涉及到另一個tip.性能
上面代碼裏面的分支徹底可使用函數來進行代替。優化
function(flag){ command.flag; } var command = (function(){ var left = function(){ move("right"); } var right = function(){ move("left"); } var top = function(){ move("bottom"); } var bottom = function(){ move("top"); } return { left,right,top,bottom } })();
這樣,雖然增長了一個對象,可是代碼確實清晰可見的。 這就是經過命令模式,來重構代碼,完成性能和閱讀的優化。
但有時候,使用分支,會比這樣更簡潔,那固然可使用分支啦。 而使用分支還要主意一個tip就是.this
這裏想說的就兩點,一是,儘量不使用分支,二是,若是嵌套分支,儘可能改成不嵌套。 不使用分支的狀況上面已經說了,若是使用分支,那麼請不要嵌套,或者說不要過分嵌套。由於一個分支已經很難閱讀了,md,你再加個嵌套,你還讓不讓人讀了。 而解決過分嵌套的方法真的是千千萬萬,我這裏就介紹一個比較簡單的。使用return 提前退出嵌套。prototype
function move(obj){ if(obj.isShow){ if(obj.isTop){ if(obj.isLeft){ return move("TopLeft"); } }else{ return false; } }else { return false; } }
這,看着爽不爽。 若是,我碰見這樣的代碼,我第一反應就是,要!死!啦!. 因此,爲了讓你的程序人性化,咱們可使用return 語句進行改寫。 咱們能夠對條件判斷的邏輯進行分析,能夠看出,裏面若是條件不知足都是返回false,那麼咱們能夠將false的狀況提取出來。插件
function move(obj){ if(!obj.isShow){ return false; } if(!obj.isTop){ return false; } if(!obj.isLeft){ return false; } return move("TopLeft"); }
這是這個feel。固然,追求極致的話,咱們能夠看出return false,是徹底一致的,固然能夠將條件合併.
function move(obj){ if(!obj.isShow||!obj.isTop||!obj.isLeft){ return false; } return move("TopLeft"); }
其實若是你數學學得好的話(我還行吧,嘿~嘿~嘿~)。 這樣提取條件的事是垂手可得的,能夠看出,上面那段古老的代碼徹底能夠變爲如今這個樣式,並且讀起來,真的不是一個檔次的。
減小參數數量的方法,固然永遠不會===1, 由於每一個人站的角度不一樣,獲得的答案固然也不同。因此這裏只介紹兩種比較通用的。
使用對象來代替參數列表。
將須要額外計算的參數忽略。
這個最突出的特色就是在寫模板的時候。
function templ(name,age,gender){ return `my name is ${name}. and I'm ${age} years old. yeah! I am a ${gender}`; }
有一個模板,上面需求的參數有三個,可是,事實上,這個是徹底不靠譜的。 由於一我的不只僅只有name,age,gender 確定還有別的參數,這樣,形成的後果就是,你一直在維護模板的同時,還須要維護參數列表。並且,還要維護,傳入參數的順序的正確性。因此這裏強烈推薦使用對象來代替多參數。
function templ(person){ return `my name is ${person.name}. and I'm ${person.age} years old. yeah! I am a ${person.gender}`; }
如今這個模板函數與外界的耦合性已經下降了很多。並且很是易於維護,就算外面你的person對象有多餘的參數,也不會妨礙我使用我須要的數據。
這種狀況主要是在作UI的時候可能會遇到,即,想繪製一個數據table的時候,須要將一個數據矩形的高,寬以及面積傳入一個函數,進行繪製。
function column(width,height,square){ console.log("矩形的寬度爲"+width); console.log("矩形的高度爲"+height); console.log("矩形的面積爲"+square); }
而,這樣作是徹底沒有必要的,由於函數參數越少,給人的感受固然越好。
咱們能夠修改成這樣.
function column(width,height){ var square = width*height; console.log("矩形的寬度爲"+width); console.log("矩形的高度爲"+height); console.log("矩形的面積爲"+square); }
並且在插件設計中,也應該準遵照這個原則,函數的參數應該在能力範圍內,把它降至最少。
這個應該算是比較高級的用法。使用過jQuery的同窗應該印象最深入。 即,咱們能夠這樣來使用一個功能.
$(".myClass").addClass("show").attr('data-name').css("display","none");
而這樣實現其實並不難,只要在每一個方法的後面返回該對象就能夠實現這個技能。
咱們來模仿一下。
var Div = function(){ } Div.prototype.createElement = function(){ console.log("建立一個Div"); return this; } Div.prototype.showDiv = function(){ console.log("顯示Div"); return this; } var div = new Div(); div.createElement().showDiv();
這樣不只能夠實現對象的細粒度,並且也知足單一職責原則。
一樣,我要說的是,覺得的使用鏈式的時候,記住,使用一個功能塊鏈式調用必定要分行,否則,調bug會調哭的。
var Div = function(){ } Div.prototype.createElement = function(){ console.log("建立一個Div"); return this; } Div.prototype.showDiv = function(){ console.log("顯示Div"); return this; } Div.prototype.hideDiv = function(){ console.log("隱藏Div"); return this; } Div.prototype.tagName = function(){ console.log("tagName 是 Div"); return this; } var div = new Div(); div.createElement().showDiv().tagName().hideDiv(); //表這樣作
上面是個反例,正確的作法,應該分開。
div.createElement() .showDiv() .tagName() .hideDiv();
像這樣調用,萬一出個Bug,你也應該知道這個bug在哪個函數塊內。大部分重構的小技巧差很少介紹完了(智商有限),若是,你們有什麼更好的建議歡迎留言反饋.