JavaScript 編碼風格指南

寫做本文旨在加深本身印象,也爲了更多人的瞭解到JS編碼風格,提升本身的編碼質量 想了解更多的內容請閱讀《編寫可維護的JavaScript》html

縮進

  • 每一行的層級由4個空格組成,避免使用製表符 (Tab) 進行縮進
// 好的寫法
if (true) {
    doSomething();
}
複製代碼

行的長度

  • 每行長度不該超過80個字符。若是一行超過80個字符,應當在一個運算符 (逗號, 加號等) 後換行。下一行應當增長兩級縮進(8個字符)
// 好的寫法
doSomething(argument1, argument2, aegument3, argument4,
        argument5);
 
// 很差的寫法:第二行只有4個空格的縮進
doSomething(argument1, argument2, aegument3, argument4,
    argument5);

// 很差的寫法:在運算符以前換行
doSomething(argument1, argument2, aegument3, argument4
        , argument5);
複製代碼

原始值

  • 字符串應當始終使用雙引號 (避免使用單引號) 且保持一行,避免在字符串中使用斜線另起一行 我的建議: html 用雙引號, js 用單引號; 反之, 亦可
// 好的寫法
var name = "Nicholas";

// 很差的寫法: 單引號
var name = 'Nicholas';

// 很差的寫法: 字符串結束以前換行
var longString = "Here's the story, of a man \ named Brady.";
複製代碼
  • 數字應當使用十進制整數,科學計算法表示整數,十六進制整數,或者十進制浮點小數,小數先後應當至少保留一位數字。避免使用八進制直接量
// 好的寫法
var count = 10;

// 好的寫法
var price = 10.0;
var price = 10.00;

// 好的寫法
var num = 0xA2;

// 好的寫法
var num = 1e23;

// 很差的寫法: 十進制數字以小數點結尾
var price = 10.;

// 很差的寫法: 十進制數字以小數點開頭
var price = .1;

// 很差的寫法: 八進制 (base 8) 寫法已廢棄
var num = 010;
複製代碼
  • 特殊值null除了下述狀況下應當避免使用
    • 用來初始化一個變量,這個變量可能被賦值爲一個對象
    • 用來和一個已經初始化的變量比較,這個變量能夠是也能夠不是一個對象
    • 當函數的參數指望是對象時,被用做參數傳入
    • 當函數的返回值指望是對象時,被用做返回值傳出
// 好的寫法
var person = null;

// 好的寫法
function getPerson() {
    if (condition) {
        return new Person("Nicholas");
    } else {
        return null;
    }
}

// 好的寫法
var person = getPerson();
if (person != null) {
    doSomething();
}

// 很差的寫法: 和一個未被初始化的變量比較
var person;
if (person != null) {
    doSomething();
}

// 很差的寫法: 經過測試判斷某個參數是否傳遞
function doSomething(arg1, arg2, arg3, arg4) {
    if (arg4 != null) {
        doSomethingElse();
    }
}
複製代碼
  • 避免使用特殊值 undefined。判斷一個變量是否認義應當使用 typeof 操做符
// 好的寫法
if (typeof variable == "undefined") {
    // do something
}
 
// 很差的寫法: 使用了 undefined 直接量
if (variable == undefined) {
    // do something
}
複製代碼

運算符間距

  • 二元運算符先後必須使用一個空格來保持表達式的整潔。操做符包括賦值運算符和邏輯運算符
// 好的寫法
var found = (values[i] === item);

// 好的寫法
if (found && (count > 10)) {
    doSomething();
}
 
// 好的寫法
for (i = 0; i < count; i++) {
    process(i);
}

// 很差的寫法: 丟失了空格
var found = (values[i]===item);
 
// 很差的寫法: 丟失了空格
if (found&&(count>10)) {
    doSomething();
}

// 很差的寫法: 丟失了空格
for (i=0; i<count; i++) {
    process(i);
}
複製代碼

括號間距

  • 當使用括號時,緊接左括號以後和緊接右括號以前不該該有空格
// 好的寫法
var found = (values[i] === item);
 
// 好的寫法
if (found && (count > 10)) {
    doSomething();
}
 
// 好的寫法
for (i = 0; i < count; i++) {
    process(i);
}

// 很差的寫法: 左括號以後有額外的空格
var found = ( values[i] === item);

// 很差的寫法: 右括號以前有額外的空格
if (found && (count > 10) ) {
    doSomething();
}

// 很差的寫法: 參數兩邊有額外的空格
for (i = 0; i < count; i++) {
    process( i );
}
複製代碼

對象直接量

  • 對象直接量應當有以下格式
    • 起始左花括號應當同表達式保持同一行
    • 每一個屬性的名值對應當保持一個縮進,第一個屬性應當在左花括號後另起一行
    • 每一個屬性的名值對應當使用不含引號的屬性名,其後緊跟一個冒號(以前不含空格),然後是值
    • 假若屬性值是函數類型,函數體應當在屬性名之下另起一行,並且其先後均應保留一個空行
    • 一組相關的屬性先後能夠插入空行以提高代碼的可讀性
    • 結束的右花括號應當獨佔一行
// 好的寫法
var object = {
 
    key1: value1,
    key2: value2,
 
    func: function() {
        // doSomething
    },
 
    key3: value3
};
 
// 很差的寫法:不恰當的縮進
var object = {
                key1: value1,
                key2: value2
          };
 
// 很差的寫法:函數體周圍缺乏空行
var object = {
 
    key1: value1,
    key2: value2,
    func: function() {
        // doSomething
    },
    key3: value3
};
複製代碼
  • 當對象字面量做爲函數參數時,若是值是變量,起始花括號應當同函數名在同一行。全部其他先前列出的規則一樣適用
// 好的寫法
doSomething({
    key1: value1,
    key2: value2
});

// 很差的寫法:全部代碼在一行上
doSomething({ key1: value1, key2: value2 });

複製代碼

註釋

  • 頻繁地使用註釋有助於他人理解你的代碼。以下狀況應當使用註釋
    • 代碼晦澀難懂
    • 可能被誤認爲錯誤的代碼
    • 必要但不明顯的針對特定瀏覽器的代碼
    • 對於對象、方法或者屬性,生成文檔是有必要的(使用恰當的文檔註釋)

單行註釋

  • 單行註釋應當用來講明一行代碼或者一組相關的代碼。單行註釋可能有三種使用方式
    • 獨佔一行的註釋,用來解釋下一行代碼
    • 在代碼行的尾部的註釋,用來解釋它以前的代碼
    • 多行,用來註釋掉一個代碼塊
// 好的寫法
if (condition) {
 
    // 若是代碼執行到這裏,則代表經過了全部安全性檢查
    allowed();
}
 
// 很差的寫法:註釋以前沒有空行
if (condition) {
    // 若是代碼執行到這裏,則代表經過了全部安全性檢查
    allowed();
}
 
// 很差的寫法:錯誤的縮進
if (condition) {
 
// 若是代碼執行到這裏,則代表經過了全部安全性檢查
    allowed();
}

// 很差的寫法:這裏應當使用多行註釋
// 接下來的這段代碼很是難,那麼,讓我詳細的解釋一下
// 這段代碼的做用氏首先判斷條件是否爲真
// 只有爲真時纔會執行。這裏的條件是經過
// 多個函數計算出來的,在整個會話生命週期內
// 這個值氏能夠被修改的
if (condition) {
    // 若是代碼執行到這裏,則代表經過了全部安全檢查
    allowed();
}
複製代碼
  • 對於代碼行尾單行註釋的狀況,應確保代碼結尾同註釋之間至少一個縮進
// 好的寫法
var result = something + somethingElse; // somethingElse will never be null
 
// 很差的寫法: 代碼和註釋間沒有足夠的空格
var result = something + somethingElse;// somethingElse will never be null
複製代碼
  • 註釋一個代碼塊時在連續多行使用單行註釋是惟一能夠接受的狀況.。多行註釋不該當在這種狀況下使用
// 好的寫法
// if (condition) {
//     doSomething();
// }
複製代碼

多行註釋

  • 多行註釋應當在代碼須要更多文字去解釋的時候使用。每一個多行註釋都至少有以下三行
    • 首行僅僅包括/*註釋開始。該行不該當有其餘文字
    • 接下來的行以*開頭並保持左對齊。這些能夠有文字描述
    • 最後一行以*/開頭並同先前行保持對齊。也不該有其餘文字
  • 多行註釋的首行應當保持同它描述代碼的相同層次的縮進。後續的每行應當有一樣層次的縮進並附加一個空格(爲了適當保持*字符的對齊)。每個多行代碼以前應當預留一個空行
// 好的寫法
if (condition) {
 
    /*
     * 若是代碼執行到這裏
     * 說明經過了全部的安全檢測
     */
    allowed();
}

// 很差的寫法: 註釋以前無空行
if (condition) {
    /*
     * 若是代碼執行到這裏
     * 說明經過了全部的安全檢測
     */
    allowed();
}

// 很差的寫法: 星號後沒有空格
if (condition) {
 
    /*
     *若是代碼執行到這裏
     *說明經過了全部的安全檢測
     */
    allowed();
}

// 很差的寫法: 錯誤的縮進
if (condition) {
 
/*
 * 若是代碼執行到這裏
 * 說明經過了全部的安全性檢測
 */
    allowed();
}
 
// 很差的寫法: 代碼尾部註釋不要用多行註釋格式
var result = something + somethingElse; /*somethingElse 不該當取值爲null*/
複製代碼

聲明

註釋聲明

  • 註釋有時候也能夠用來給一段代碼聲明額外的信息。這些聲明的格式以單個單詞打頭並緊跟一個冒號。可使用的聲明以下
    • TODO
      • 說明代碼還未完成。應當包含下一步要作的事情
    • HACK
      • 代表代碼實現走了一個捷徑。應當包含爲什麼使用 hack 的緣由。這也可能代表該問題可能會有更好的解決辦法
    • XXX
      • 說明代碼是有問題的並應當儘快修復
    • FIXME
      • 說明代碼是有問題的並應儘快修復。重要性略次於XXX
    • REVIEW
      • 說明代碼在任何可能的改動都須要評審
  • 這些聲明可能在一行或者多行註釋中使用,而且應當遵循同通常註釋類型相同的格式規則
// 好的寫法
// TODO: 我但願找到一種更快的方式
doSomething();

// 好的寫法
/*
 * HACK: 不得不針對 IE 作的特殊處理. 我計劃後續有時間時
 * 重寫這部分. 這些代買可能須要在 v1.2 版本以前替換掉
 */
if (document.all) {
    doSomething();
}

// 好的寫法
// REVIEW: 有更好的方法嗎?
if (document.all) {
    doSomething();
}

// 很差的寫法: 註釋聲明空格不正確
// TODO :  我但願找到一種更快的方式
doSomething();
 
// 很差的寫法: 代碼和註釋應當保持一樣的縮進
    // REVIEW: 有更好的方法嗎?
if (document.all) {
    doSomething();
}
複製代碼

變量聲明

  • 全部的變量在使用前都應當事先定義。變量定義應當放在函數開頭,使用一個 var 表達式每行一個變量。除了首行,全部行都應當多一層縮進以使變量名可以垂直方向對齊。變量定義時應當初始化,而且賦值操做符應當爆出一致的縮進。初始化的變量應當在未初始化變量以前
// 好的寫法
var count = 10,
      name = "Nicholas",
      found = false,
      empty;

// 很差的寫法: 不恰當的初始化賦值
var count = 10,
     name = "Nicholas",
     found= false,
     empty;

// 很差的寫法: 錯誤的縮進
var count = 10,
name = "Nicholas",
found = false,
empty;

// 很差的寫法: 多個定義寫在一行
var count = 10, name = "Nicholas", 
      found = false, empty;

// 很差的寫法: 未初始化的變量放在最前面
var empty,
      count = 10,
      name = "Nicholas",
      found = false;

// 很差的寫法: 多個 var 表達式
var count = 10,
      name = "Nicholas";

var found = false,
      empty;
複製代碼

函數聲明

  • 函數應當在使用前提早定義。一個不是做爲方法的函數(也就是說沒有做爲一個對象的屬性)應當使用函數定義的格式(不是函數表達式和 Function 構造器格式)。函數名和開始圓括號之間不該當有空格。結束的圓括號和右邊的花括號之間應該留一個空格。右側的花括號應當同 function 關鍵字保持同一行。開始和結束括號之間不該該有空格。參數名之間應當在都好以後保留一個空格。函數體應當保持一級縮進。
// 好的寫法
function doSomething(arg1, arg2) {
    return arg1 + arg2;
}

// 很差的寫法: 第一行不恰當的空格
function doSomething (arg1, arg2) {
    return arg1 + arg2;
}

// 很差的寫法: 函數表達式
var doSomething = function doSomething(arg1, arg2) {
    return arg1 + arg2;
}

// 很差的寫法: 左側的花括號位置不對
function doSomething(arg1, arg2) 
{
    return arg1 + arg2;
}

// 錯誤的寫法: 使用了 Function 構造器
var doSomething = new Function("arg1", "arg2", "return arg1 + arg2")
複製代碼
  • 其餘函數內部定義的函數應當在 var 語句後當即定義
// 好的寫法
function outer() {
    
    var count = 10,
        name = "Nicholas",
        found = false,
        empty;

    function inner() {
        // 代碼
    }

    // 調用 inner() 的代碼
}

// 很差的寫法: inner 函數的定義先於變量
function outer() {
    
    function inner() {
        // 代碼
    }
    
    var count = 10,
        name = "Nicholas",
        found = false,
        empty;

    // 調用 inner() 的代碼
}
複製代碼
  • 匿名函數可能做爲方法賦值給對象,或者做爲其餘函數的參數。function 關鍵字同開始括號之間不該有空格
// 好的寫法
object.method = function() {
    // 代碼
};

// 很差的寫法: 不正確的空格
object.method = function () {
    // 代碼
};
複製代碼
  • 當即被調用的函數應當在行數調用的外層用圓括號包裹
// 好的寫法
var value = (function() {
    
    // 函數體

    return {
        message: "Hi"
    }
}());

// 很差的寫法: 函數調用外層沒有用圓括號包裹
var value = function() {
    
    // 函數體

    return {
        message: "Hi"
    }
}();

// 很差的寫法: 圓括號位置不當
var value = (function() {
    
    // 函數體

    return {
        message: "Hi"
    }
})();
複製代碼

賦值

  • 給變量賦值時,若是右側是含有比較語句的表達式,須要用圓括號包裹
// 好的寫法
var flag = (i < count);
 
// 很差的寫法:遺漏圓括號
var flag = i < count;
複製代碼

命名

  • 變量和函數在命名時應當當心。命名應僅限於數字字母字符,某些狀況下可使用下劃線。最好不要在任何命名中使用美圓符號($)或者反斜槓(\)
  • 變量命名應當採用駝峯命名格式,首字母小寫,每一個單詞首字母大寫。變量名的第一個單詞應當是一個名詞 (而非動詞) 以免同函數混淆。不要在變量名中使用下劃線
// 好的寫法
var accountNumber = "2312";
  
// 很差的寫法:大寫字母開頭
var AccountNumber = "2312";
 
// 很差的寫法:動詞開頭
var getAccountNumber = "2312";
 
// 很差的寫法:使用下劃線
var account_number = "2312";
複製代碼
  • 函數名也應當採用駝峯命名格式。函數名的第一個單詞應當是動詞(而非名詞)來避免同變量混淆。函數名中最好不要使用下劃線
// 好的寫法
function doSomething() {
    // 代碼
}
 
// 很差的寫法:大寫字母開頭
function DoSomething() {
    // 代碼
}
 
// 很差的寫法:名詞開頭
function something() {
    // 代碼
}
 
// 很差的寫法:使用下劃線
function do_something() {
    // 代碼
}
複製代碼
  • 這裏有一些使用動詞常見的約定
動詞 含義
can 函數返回一個布爾值
has 函數返回一個布爾值
is 函數返回一個布爾值
get 函數返回一個非布爾值
set 函數用來保存一個值
if (isEnabled()) {
    setName("Nicholas");
}

if (getName() === "Nicholas") {
    doSomething();
}
複製代碼
  • 構造函數——經過new運算符建立新對象的函數——也應當以駝峯格式命名而且首字符大寫。構造函數名稱應當以非動詞開頭,由於new表明着建立一個對象實例的操做
// 好的寫法
function MyObject() {
    // 代碼
}

// 很差的寫法:小寫字母開頭
function myObject() {
    // 代碼
}

// 很差的寫法:使用下劃線
function my_object() {
    // 代碼
}

// 很差的寫法:動詞開頭
function getMyObject() {
    // 代碼
}
複製代碼
  • 常量(值不會被改變的變量)的命名應當是全部大寫字母,不一樣單詞之間單個下劃線隔開
// 好的寫法
var TOTAL_COUNT = 10;
 
// 很差的寫法:駝峯形式
var totalCount = 10;
 
// 很差的寫法:混合形式
var total_COUNT = 10;
複製代碼
  • 對象的屬性同變量的命名規則相同。對象的方法同函數的命名規則相同。若是屬性或者方法是私有的,應當在以前加上一個下劃線
// 好的寫法
var object = {
    _count: 10,

    _getCount: function() {
        return this._count;
    }
}
複製代碼

嚴格模式

  • 嚴格模式應當僅限在函數內部使用,千萬不要在全局使用
// 很差的寫法:全局使用嚴格模式
"use strict";
 
function doSomething() {
    // 代碼
}
  
// 好的寫法
function doSomething() {
    "use strict";

    // 代碼
}
複製代碼
  • 若是你指望在多個函數中使用嚴格模式而不須要屢次聲明「use strict」,可使用當即被調用的函數
// 好的寫法
(function() {
    "use strict";

    function doSomething() {
        // 代碼
    }

    function doSomethingElse() {
        // 代碼
    }
}());
複製代碼

運算符

等號運算符

  • 使用===(嚴格相等)和!==(嚴格不相等)代替==(相等)和!=(不等)來避免弱類型轉換錯誤
// 好的寫法
var same = (a === b);
 
// 好的寫法
var same = (a == b);
複製代碼

三元運算符

  • 三元運算符應當僅僅用在條件賦值語句中,而不要做爲if語句的替代品
// 好的寫法
var value = condition ? value1 : value2;
 
// 很差的寫法: 沒有賦值, 應當使用 if 表達式
condition ? doSomething() : doSomethingElse;
複製代碼

語句

簡單語句

  • 每一行最多隻包含一條語句。全部簡單的語句都應該以分號(;)結束
// 好的寫法
count++;
a = b;
 
// 很差的寫法:多個表達式寫在一行
count++; a = b;
複製代碼
  • 返回語句
    • 返回語句當返回一個值的時候不該當使用圓括號包裹,除非在某些狀況下這麼作可讓返回值更容易理解。例如
return;
 
return collection.size();
 
return (size > 0 ? size : defaultSize);
複製代碼

複合語句

  • 複合語句是大括號括起來的語句列表
    • 括起來的語句應當較複合語句多縮進一個層級
    • 開始的大括號應當在複合語句所在行的末尾;結束的大括號應當獨佔一行且同複合語句的開始保持一樣的縮進
    • 當語句是控制結構的一部分時,諸如 if 或者 for 語句,全部語句都須要用大括號括起來,也包括單個語句。這個約定使得咱們更方便地添加語句而不用擔憂忘記加括號而引發 bug
    • 像 if 同樣的語句開始的關鍵詞,其後應該緊跟一個空格,起始大括號應當在空格以後

if 語句

  • if 語句應當是下面的格式
if (condition) {
    statements
}
 
if (condition) {
    statements
} else {
    statements
}
 
if (condition) {
    statements
} else if (condition) {
    statements
} else {
    statements
}
複製代碼
  • 毫不容許在if語句中省略花括號
// 好的寫法
if (condition) {
    doSomething();
}
 
// 很差的寫法:不恰當的空格
if (condition){
    doSomething();
}

// 很差的寫法: 遺漏花括號
if (condition)
    doSomething(); 

// 很差的寫法:全部代碼都在一行
if (condition) { doSomething(); }
 
// 很差的寫法:全部代碼都在一行且沒有花括號
if (condition) doSomething();
複製代碼

for 語句

  • for 類型的語句應當是下面的格式
for (initialization; condition; update) {
    statements
}

for (variable in object) {
    statements
}
複製代碼
  • for語句的初始化部分不該當有變量聲明
// 好的方法
var i,
    len;
 
for (i=0, len=0; i < len; i++) {
    // 代碼
}
 
// 很差的寫法:初始化時候聲明變量
for (var i=0, len=0; i < len; i++) {
    // 代碼
}
 
// 很差的寫法:初始化時候聲明變量
for (var prop in object) {
    // 代碼
}
複製代碼
  • 當使用for-in語句時,記得使用hasOwnProperty()進行雙重檢查來過濾對象的成員

while 語句

  • while 類的語句應當是下面的格式
while (condition) {
    statements
}
複製代碼

do 語句

  • do 類的語句應當是下面的格式
do {
    statements
} while (condition);
複製代碼

switch 語句

  • switch 類的語句應當是以下格式
switch (expression) {
    case expression:
        statements
 
    default:
        statements
}
複製代碼
  • switch 下的第一個 case 都應當保持一個縮進。除第一個以外包括 default 在內的每個 case 都應當在以前保持一個空行
  • 每一組語句(除了default)都應當以 break、return、throw 結尾,或者用一行註釋表示跳過
// 好的寫法
switch (value) {
    case 1:
        /* falls through */
 
    case 2:
        doSomething();
        break;
 
    case 3:
        return true;
 
    default:
        throw new Error("Some error");
}
複製代碼
  • 若是一個switch語句不包含default狀況,應當用一行註釋代替
// 好的寫法
switch (value) {
  case 1:
    /* falls through */
 
  case 2:
    doSomething();
    break;
 
  case 3:
    return true;
 
  default:
    // 沒有default
}
複製代碼

try 語句

  • try類的語句應當格式以下
try {
    statements
} catch (variable) {
    statements
}

try {
    statements
} catch (variable) {
    statements
} finally {
    statements
}
複製代碼

留白

  • 在邏輯相關的代碼之間添加空行代碼能夠提升代碼的可讀性
  • 兩行空行僅限於在以下狀況下使用
    • 在不一樣的源代碼文件之間
    • 在類和接口定義之間
  • 單行空行僅限在以下狀況中使用
    • 方法之間
    • 方法中局部變量和第一行語句之間
    • 多行或者單行註釋以前
    • 方法中邏輯代碼塊之間以提高代碼的可讀性
  • 空格應當在以下的狀況下使用
    • 關鍵詞後跟括號的狀況應當用空格隔開
    • 參數列表中逗號以後應當保留一個空格
    • 全部的除了點(.)以外的二元運算符,其操做數都應當用空格隔開。單目運算符的操做數之間不該該用空白隔開,例如一元減號,遞增(++),遞減(--)
    • for 語句的表達式之間應當用空格隔開

注意

  • 切勿使用像 String 一類的原始包裝類型建立新的對象
  • 避免使用 eval()
  • 避免使用with語句。該語句在嚴格模式中不復存在,可能在將來的ECMAScript 標準中也將去除

最後

  • 上述指南並非在開發過程當中必須徹底遵照的 (好比說引號和縮進等),咱們能夠只汲取其中的一部分來改善本身的編碼風格,讓本身的代碼易讀、可維護。關於編碼風格,每一個團隊都有本身的特點,只要保持團隊一致性,能夠高效的開發就OK了
相關文章
相關標籤/搜索