編寫可維護的JavaScript

china-pub發表於2013-03-08

軟體生命週期中80%的成本都消耗在了維護上;而且幾乎所有的維護者都不是程式碼的直接開發人。如何讓自己寫的程式碼讓別人閱讀起來更高效?當然是寫程式碼的時候注入一些規範。那麼在Javascript中有哪些程式設計風格值得我們去注重呢?這篇文章將總結《編寫可維護的JavaScript》裡面的觀點。

縮排風格

image
上圖是Stack Overflow的調查,可見,大部分的Programmer都喜歡用tab進行縮排。每行縮排由4個空格組成。

語句結尾

建議不要省略分號。很多人喜歡寫js程式碼很依賴於自動分號插入,也就是語句後面不加分號。但是這是大多數的情況,像return這樣的語句是會出錯的。類似的還有其他一些語法,這裡就不細說自動分號插入機制了,感興趣的童鞋可以前往JavaScript ASI 機制詳解

行的長度

這個之前在另外一篇部落格中有介紹過,為了保證在小屏筆記本和大螢幕上看到的程式碼是一致的,通常建議每一行程式碼不要超過80列。

換行

程式碼長度超過80列,換行也是有講究的。建議換行的程式碼增加兩個縮排長度。例如:

callFunction(element1, element2, element3, element4,
        element5);
複製程式碼

空行

整個函式程式碼沒有空行地緊湊在一起會給閱讀程式碼的人一定的視覺疲勞。也讓人厭倦,起碼我看到這樣的程式碼就不想再看下去了。對於空行地建議:

  • 在方法之間
  • 在方法中的區域性變數和第一條語句之間
  • 在註釋之前
  • 在方法內的邏輯片段之間插入空行,提高可讀性

命名

命名是我覺得規範中最難的點,怎麼讓變數或者函式名稱還有意境。結合不同的場景,設定不一樣的名稱。讓維護程式碼的人像看小說一般地閱讀程式碼,就說明命名是成功的!除了變數含義之外,其他的一些規範比如:

  • 駝峰寫法
  • 變數用名詞
  • 函式用動詞+名詞
  • 物件私有屬性或方法前面加_
  • 常量用全部大寫字母且分割單詞用下劃線
  • 建構函式首字母大寫,且以非動詞開頭

註釋

單行註釋

  • 獨佔一行,用來解釋下一行程式碼
if (condition) {
    
    // 如果程式碼執行到這裡,代表通過了condition的校驗
    next();
}
複製程式碼

注意註釋之前要加空行、註釋也要縮排。

  • 與程式碼同一行,用來解釋之前的程式碼
var result = something + somethingElse;    // somethingElse will never be null
複製程式碼

注意註釋與程式碼直接至少新增一個縮排。

  • 多行,用來註釋掉一個程式碼塊
// if (condition) {
//     doSomething();
//     doSomethingElse();
// }
複製程式碼

註釋一個程式碼塊時是在連續多行使用單行註釋唯一可以接受的情況。但是最好別這樣使用。

多行註釋

if (condition) {

    /*
     * 如果程式碼執行到這裡
     * 說明balabala
     */
     doSomething();
}
複製程式碼

要注意縮排、換行、空格、空行。

使用註釋宣告

註釋說明,主要用來做記號。主要有以下幾種:

  • TODO 說明程式碼還未完成,說明接下來要做的事情。
  • HACK 表明程式碼實現走了一個捷徑。應當包含為何使用hack的原因。同時也表明也許會有更好的解決辦法。
  • FIXME 說明程式碼存在bug,應當儘快修復。
  • REVIEW 說明程式碼任何可能的改動都需要評審。

變數、函式和運算子

  • 變數宣告 變數宣告習慣一般有兩種:一種是“就近”原則,放在離使用最近的地方;第二種就是放在最上面,作為函式內的第一條語句。個人推薦後者,這跟JavaScript引擎解析程式碼的習慣是一致的。

  • 函式宣告 函式宣告也會被JS引擎提前,建議在函式呼叫之前宣告函式。另外,推薦函式內部的區域性函式應當緊接著變數宣告之後宣告。

  • 立即呼叫的函式 立即執行函式,在開發中肯定會經常使用。好的寫法是:

var value = (function() {

    // 函式體
    return {
        message: 'Hi'
    };
}());
複製程式碼

清晰明瞭地的讓人知道這是一個立即執行函式。

  • 嚴格模式 ES5引入了嚴格模式,通過這種方式解析執行js程式碼,來達到減少錯誤的目的。程式碼要以strict mode去解析也很簡單,只要將use strict放到js程式碼中即可。當js解析器看到這樣一條沒有賦給變數的字串之後,就會以嚴格模式去解析程式碼。一個原則:儘量少地影響到更多程式碼!什麼意思呢?use strict可以放到任何位置,全域性或者函式區域性都可以。
// bad
"use strict";
function doSomething() {
    // 程式碼

}

// good
function doSomething() {
    "use strict";
    // 程式碼

}
複製程式碼

如果有多個函式要使用嚴格模式,就用立即函式限制起來,避免影響到全域性。

(function() {
    "use strict";
    function doSomething() {
        // 程式碼
    }
    function doSomethingElse() {
        // 程式碼
    }
})();
複製程式碼
  • 相等 使用===、!==代替==、!=,避免型別轉換。型別轉換的相關內容這裡就不說了,自行了解。

UI層的鬆耦合

鬆耦合的原則:修改一個元件時儘可能不需要修改其他元件程式碼。

  • 將JavaScript從CSS中抽離 避免使用CSS表示式

  • 將CSS從JavaScript中抽離 避免直接修改dom的樣式,通過類名去實現想要的效果。

// bad
element.style.cssText = "color: red; left: 10px";

// good
.reveal {
    color: red;
    left: 10px;
}

element.className += " reveal";
複製程式碼
  • 將JavaScript從HTML中抽離 避免直接在HTML寫事件處理程式和邏輯程式碼

事件處理

兩個規則:

  • 隔離程式邏輯 將應用邏輯從所有事件處理程式中抽離出來是最佳實踐,舉個例子:
// bad
function handleClick(event) {
    var popup = document.getElementById("popup");
    popup.style.left = event.clientX + "px";
    popup.style.top = event.clientY + "px";
    popup.className = "reveal";
}

// good
function handleClick(event) {
    showPopup(event);
}

function showPopup(event) {
    popup.style.left = event.clientX + "px";
    popup.style.top = event.clientY + "px";
    popup.className = "reveal";
}
複製程式碼
  • 不要濫用事件物件 將事件物件event一直傳遞下去是個很爛的實踐。別人並不知道你具體使用到事件物件的什麼屬性或者方法。繼續用上面的例子:
// bad
function handleClick(event) {
    showPopup(event);
}

function showPopup(event) {
    popup.style.left = event.clientX + "px";
    popup.style.top = event.clientY + "px";
    popup.className = "reveal";
}

// good
function handleClick(event) {
    showPopup(event.clientX, event.clientY);
}

function showPopup(x, y) {
    popup.style.left = x + "px";
    popup.style.top = y + "px";
    popup.className = "reveal";
}
複製程式碼

vue的規範建議可以前往vue最佳實踐,一起討論學習吧!

相關文章