1. 程式人生 > 實用技巧 >11個 Javascript 小技巧幫你提升程式碼質量,乾貨收藏!

11個 Javascript 小技巧幫你提升程式碼質量,乾貨收藏!

Javascript 常用程式碼優化和重構的方法

簡介

主要介紹以下幾點:

  1. 提煉函式

  2. 合併重複的條件片段

  3. 把條件分支語句提煉成函式

  4. 合理使用迴圈

  5. 提前讓函式退出代替巢狀條件分支

  6. 傳遞物件引數代替過長的引數列表

  7. 少用三目運算子

  8. 合理使用鏈式呼叫

  9. 分解大型類

  10. 活用位操作符

  11. 純函式

  12. 整理了一份Java面試寶典完整版PDF

本文會不斷更新,不足之處歡迎補充。

1. 提煉函式

好處:

  • 避免出現超大函式。

  • 獨立出來的函式有助於程式碼複用。

  • 獨立出來的函式更容易被覆寫。

  • 獨立出來的函式如果擁有一個良好的命名,它本身就起到了註釋的作用。

  • 語義化將多段分離的邏輯放在不同的函式中實現,可以使程式碼邏輯清晰,清楚的看到每一步在做什麼。

程式碼舉例:

實現獲取資料,然後操作dom顯示資料,最後新增事件

  • 函式提煉前

//邏輯都寫在一起,需要將所有邏輯看完才知道這段程式碼是幹嘛的,區域性邏輯無法複用
functionmain(){
$.ajax.get('/getData').then((res)=>{
constul=document.getElementById('ul');
ul.innerHTML=res.list.map(text=>`<liclass="li">${text}</li>`).join('\n');
constlist=document.getElementsByClassName('li');
for(leti=0;i<list.length;i++){
list[i].addEventListener('focus',()=>{
//dosomething
});
}
});
}


  • 函式提煉後

functiongetData(){
return$.ajax.get('/getData').then((res)=>res.data.list);
}
functionshowList(list){
constul=document.getElementById('ul');
ul.innerHTML=list.map(text=>`<liclass="li">${text}</li>`).join('\n');
}
functionaddEvent(){
constlist=document.getElementsByClassName('li');
for(leti=0;i<list.length;i++){
list[i].addEventListener('focus',()=>{
//dosomething
});
}
}
//邏輯清晰,一眼讀懂每一步在做什麼,某些提煉出來的函式還可以被複用
asyncfunctionmain(){
constlist=awaitgetData();//獲取資料
showList(list);//顯示頁面
addEvent();//新增事件
}


2. 合併重複的條件片段

如果一個函式體內有一些條件分支語句,而這些條件分支語句內部散佈了一些重複的程式碼,那麼就有必要進行合併去重工作。

//合併前
functionmain(currPage){
if(currPage<=0){
currPage=0;
jump(currPage);//跳轉
}elseif(currPage>=totalPage){
currPage=totalPage;
jump(currPage);//跳轉
}else{
jump(currPage);//跳轉
}
};

//合併後
functionmain(currPage){
if(currPage<=0){
currPage=0;
}elseif(currPage>=totalPage){
currPage=totalPage;
}
jump(currPage);//把jump函式獨立出來
};


3. 把條件分支語句提煉成函式

複雜的條件分支語句是導致程式難以閱讀和理解的重要原因,而且容易導致一個龐大的函式。有時可以將條件分支語句提煉成語義化的函式,使程式碼更加直觀,邏輯清晰。

//根據不同季節決定打折力度
functiongetPrice(price){
vardate=newDate();
if(date.getMonth()>=6&&date.getMonth()<=9){//夏天
returnprice*0.8;
}
returnprice;
};


//是否是夏天
functionisSummer(){
vardate=newDate();
returndate.getMonth()>=6&&date.getMonth()<=9;
};
//提煉條件後
functiongetPrice(price){
if(isSummer()){
returnprice*0.8;
}
returnprice;
};


4. 合理使用迴圈

如果多段程式碼實際上負責的是一些重複性的工作,那麼可以用迴圈代替,使程式碼量更少。

//判斷是什麼瀏覽器
functiongetBrowser(){
conststr=navigator.userAgent;
if(str.includes('QQBrowser')){
return'qq';
}elseif(str.includes('Chrome')){
return'chrome';
}elseif(str.includes('Safari')){
return'safri';
}elseif(str.includes('Firefox')){
return'firefox';
}elseif(explorer.indexOf('Opera')>=0){
return'opera';
}elseif(str.includes('msie')){
return'ie';
}else{
return'other';
}
};


//迴圈判斷,將對應關係抽象為配置,更加清晰明確
functiongetBrowser(){
conststr=navigator.userAgent;
constlist=[
{key:'QQBrowser',browser:'qq'},
{key:'Chrome',browser:'chrome'},
{key:'Safari',browser:'safari'},
{key:'Firefox',browser:'firefox'},
{key:'Opera',browser:'opera'},
{key:'msie',browser:'ie'},
];
for(leti=0;i<list.length;i++){
constitem=list[i];
if(str.includes(item.key)){returnitem.browser};
}
return'other';
}



5. 提前讓函式退出代替巢狀條件分支

讓函式變成多出口提前返回,替換巢狀條件分支

functiondel(obj){
varret;
if(!obj.isReadOnly){//不為只讀的才能被刪除
if(obj.isFolder){//如果是資料夾
ret=deleteFolder(obj);
}elseif(obj.isFile){//如果是檔案
ret=deleteFile(obj);
}
}
returnret;
};

functiondel(obj){
if(obj.isReadOnly){//反轉if表示式
return;
}
if(obj.isFolder){
returndeleteFolder(obj);
}
if(obj.isFile){
returndeleteFile(obj);
}
};


6. 傳遞物件引數代替過長的引數列表

函式引數過長那麼就增加出錯的風險,想保證傳遞的順序正確就是一件麻煩的事,程式碼可讀性也會變差,儘量保證函式的引數不會太長。如果必須傳遞多個引數的話,建議使用物件代替。

一般來說,函式引數最好不要超過3個

functionsetUserInfo(id,name,address,sex,mobile,qq){
console.log('id='+id);
console.log('name='+name);
console.log('address='+address);
console.log('sex='+sex);
console.log('mobile='+mobile);
console.log('qq='+qq);
};
setUserInfo(1314,'sven','shenzhen','male','137********',377876679);

functionsetUserInfo(obj){
console.log('id='+obj.id);
console.log('name='+obj.name);
console.log('address='+obj.address);
console.log('sex='+obj.sex);
console.log('mobile='+obj.mobile);
console.log('qq='+obj.qq);
};
setUserInfo({
id:1314,
name:'sven',
address:'shenzhen',
sex:'male',
mobile:'137********',
qq:377876679
});


7. 少用三目運算子

三目運算子效能高,程式碼量少。

但不應該濫用三目運算子,我們應該在簡單邏輯分支使用,在複雜邏輯分支避免使用。

//簡單邏輯可以使用三目運算子
varglobal=typeofwindow!=="undefined"?window:this;

//複雜邏輯不適合使用
varok=isString?(isTooLang?2:(isTooShort?1:0)):-1;


8. 合理使用鏈式呼叫

優點:鏈式呼叫使用簡單,程式碼量少。

缺點:鏈式呼叫帶來的壞處就是在除錯不方便,如果我們知道一條鏈中有錯誤出現,必須得先把這條鏈拆開才能加上一些除錯 log 或者增加斷點,這樣才能定位錯誤出現的地方。

如果該鏈條的結構相對穩定,後期不易發生修改,可以使用鏈式。

varUser={
id:null,
name:null,
setId:function(id){
this.id=id;
returnthis;
},
setName:function(name){
this.name=name;
returnthis;
}
};
User
.setId(1314)
.setName('sven');

varuser=newUser();
user.setId(1314);
user.setName('sven');


9. 分解大型類

大型類的分解和函式的提煉很像,類太大會出現邏輯不清晰,難以理解和維護的問題。

合理的大類分解可以使類的邏輯清晰,且子模組可以方便複用。

10. 活用位操作符

程式語言計算乘除的效能都不高,但是某些情況使用位操作符可以提升乘除等運算的效能。

11. 純函式

純函式是指不依賴於不改變它作用域之外的變數狀態的函式。

純函式的返回值只由它呼叫時的引數決定,它的執行不依賴於系統的狀態(執行上下文)。

相同的輸入引數,一定會得到相同的輸出,也就是內部不含有會影響輸出的隨機變數

不屬於純函式的特點:

  • 更改檔案系統

  • 往資料庫插入記錄

  • 傳送一個 http 請求

  • 可變資料

  • 列印/log

  • 獲取使用者輸入

  • DOM 查詢

  • 訪問系統狀態

純函式的作用:

  • 可靠性:函式返回永遠和預期一致

  • 可快取性:因為只要輸入一樣輸出一定一樣,因此可將輸入作為key,輸出作為值,使用物件快取已經計算的結果

  • 可移植性:因為沒有外部依賴,所以移植到任何環境都可正確執行

  • 可測試性:方便針對函式做單元測試

  • 可並行性:對一些複雜計算,可以平行計算(例如使用nodejs多個子程序同時平行計算多個任務,提高計算速度)

應用場景:

vara=1;
//非純函式
functionsum(b){
returna+b;
}
//非純函式
functionsum(b){
a=2;
returnb;
}
//非純函式
functionsum(b){
returnb+Math.random();
}


//純函式
functionsum(b,c){
returnb+c;
}