以下是我《JS深入淺出》第6課的講義,如果對你有幫助點個贊即可
這次課講的是「如何提高程式碼的可讀性」,跟前端關係不大,是寫程式碼的普遍技巧。
注意我們講得不是「如何提高程式碼的效能」。
程式碼優化基本原則
- 易讀性優先
- 如果不是效能瓶頸,就不要為了效能而改寫程式碼
- 複雜性守恆原則:無論你怎麼寫程式碼,複雜性都是不會消失的 推論:如果邏輯很複雜,那麼程式碼看起來就應該是複雜的。如果邏輯很簡單,程式碼看起來就應該是簡單的。
命名
程式設計師三大難題
- 變數命名
- 快取失效
- 迴圈邊界 可見變數命名的重要性。
網上有很多命名規範,大家可以參考。本節課只講基本原則。
一、注意詞性
- 普通變數/屬性用「名詞」
var person = {
name: 'Frank'
}
var student = {
grade: 3,
class: 2
}
複製程式碼
- bool變數/屬性用「形容詞」或者「be動詞」或者「情態動詞」或者「hasX」
var person = {
dead: false, // 如果是形容詞,前面就沒必要加 is,比如isDead 就很廢話
canSpeak: true, //情態動詞有 can、should、will、need 等,情態動詞後面接
動詞
isVip: true, // be 動詞有 is、was 等,後面一般接名詞
hasChildren: true, // has 加名詞
}
複製程式碼
- 普通函式/方法用「動詞」開頭
var person = {
run(){}, // 不及物動詞
drinkWater(){}, // 及物動詞
eat(foo){}, // 及物動詞加引數(引數是名詞)
}
複製程式碼
- 回撥、鉤子函式用「介詞」開頭,或用「動詞的現在完成時態」
var person = {
beforeDie(){},
afterDie(){},
// 或者
willDie(){}
dead(){} // 這裡跟 bool 衝突,你只要不同時暴露 bool dead 和函式 dead 就行,怕衝突就用上面的 afterDie
}
button.addEventListener('click', onButtonClick)
var component = {
beforeCreate(){},
created(){},
beforeMount(){},
mounted(){},
beforeUpdate(){},
updated(){},
activated(){},
deactivated(){},
beforeDestroy(){},
destroyed(){},
errorCaptured(){}
}
複製程式碼
- 容易混淆的地方加字首
div1.classList.add('active') // DOM 物件
div2.addClass('active') // jQuery 物件
不如改成
domDiv1 或 elDiv1.classList.add('active')
$div2.addClass('active')
複製程式碼
屬性訪問器函式可以用名詞
$div.text() // 其實是 $div.getText()
$div.text('hi') // 其實是 $div.setText('hi')
複製程式碼
二、注意一致性
- 介詞一致性 如果你使用了 before + after,那麼就在程式碼的所有地方都堅持使用 如果你使用了 before + 完成時,那麼就堅持使用 如果你改來改去,就「不一致」了,不一致將導致「不可預測」
- 順序一致性 比如 updateContainerWidth 和 updateHeightOfContainer 的順序就令人很彆扭,同樣會引發「不可預測」
- 表裡一致性 函式名必須完美體現函式的功能,既不能多也不能少。 比如
function getSongs(){
return $.get('/songs).then((response){
div.innerText = response.songs
})
}
複製程式碼
就違背了表裡一致性,getSongs 表示獲取歌曲,並沒有暗示這個函式會更新頁面,但是實際上函式更新了 div,這就是表裡不一,正確的寫法是
- 要麼糾正函式名
function getSongsAndUpdateDiv(){
return $.get('/songs).then((response){
div.innerText = response.songs
})
}
複製程式碼
- 要麼寫成兩個函式
function getSongs(){
return $.get('/songs)
}
function updateDiv(songs){
div.innerText = response.songs
}
getSongs().then((response)=>{
updateDiv(response.songs)
})
複製程式碼
- 時間一致性 有可能隨著程式碼的變遷,一個變數的含義已經不同於它一開始的含義了,這個時候你需要及時改掉這個變數的名字。 這一條是最難做到的,因為寫程式碼容易,改程式碼難。如果這個程式碼組織得不好,很可能會出現牽一髮而動全身的情況(如全域性變數就很難改)
改程式碼
如果你的程式碼有單元測試,那麼改起來就很放心。如果沒有單元測試,就需要用「小步快跑」的策略來修改。
小步快跑的意思是說,每次只修改一點點,測試通過後,再修改一點點,再測試,再修改一點點……如此反覆。
那麼如何修改一點點呢?《重構》這本書介紹了很多方法,但是講得有點抽象的,如果你有時間可以看看。
我這裡只說兩個經久不衰的方法。
一、使用函式來改程式碼
步驟:
- 將一坨程式碼放到一個函式裡
- 將程式碼依賴的外部變數作為引數
- 將程式碼的輸出作為函式的返回值
- 給函式取一個合適的名字
- 呼叫這個函式並傳入引數
- 這個函式裡的程式碼如果超過 5 行,則依然有優化的空間,請回到第 1 步
二、使用物件來改程式碼
如果使用了函式改造法改造後,發現有太多的小函式,則可以使用物件將這些函式串起來。
記得我們講過「this 是函式和物件的橋樑」嗎,我們會用 this 來串聯這個物件和所有函式。
最終程式碼:http://js.jirengu.com/mimazaboke/1/edit?html,js,output
一些固定的套路
- 表驅動程式設計(《程式碼大全》裡說的) 所有一一對應的關係都可以用表來做
- 自說明程式碼(以 API 引數為例) 把別人關心的東西放在顯眼的位置
bad smell(壞味道)
有些程式碼可以用,但是很「臭」。
哪些程式碼是有壞味道的
- 表裡不一的程式碼
- 過時的註釋
- 邏輯很簡單,但是看起來很複雜的程式碼
- 重複的程式碼
- 相似的程式碼
- 總是一起出現的程式碼
破窗效應
此理論認為環境中的不良現象如果被放任存在,會誘使人們仿效,甚至變本加厲。一幢有少許破窗的建築為例,如果那些窗不被修理好,可能將會有破壞者破壞更多的窗戶。最終他們甚至會闖入建築內,如果發現無人居住,也許就在那裡定居或者縱火。一面牆,如果出現一些塗鴉沒有被清洗掉,很快的,牆上就佈滿了亂七八糟、不堪入目的東西;一條人行道有些許紙屑,不久後就會有更多垃圾,最終人們會視若理所當然地將垃圾順手丟棄在地上。這個現象,就是犯罪心理學中的破窗效應。
程式設計師要做到:只要是經過你手的程式碼,都會比之前好一點。
加微訊號: astak10或者長按識別下方二維碼進入前端技術交流群 ,暗號:寫程式碼啦
每日一題,每週資源推薦,精彩部落格推薦,工作、筆試、面試經驗交流解答,免費直播課,群友輕分享... ,數不盡的福利免費送