JavaScript編碼風格指南

首次發表在我的博客javascript

前言

程序語言的編碼風格指南對於一個長期維護的軟件而言是很是重要的;好的編程風格有助於寫出質量更高、錯誤更少、更易於 維護的程序。html

團隊合做須要制定一些代碼規範還有利用一些工具來強制要求團隊代碼的風格統一.畢竟不少狀況下之後不必定是由寫一手代碼的人來維護代碼,因此有一個統一的代碼風格很重要!!!前端

最近看了一下編寫可維護的JavaScript編寫高質量代碼:Web前端開發修煉之道,根據書中提倡的一些寫法,同時結合我我的的經驗和喜愛作了一些改動,大體整理了以下JavaScript編碼風格vue

JavaScript編碼風格

1.縮進

每一行的層級由4個空格組成,避免使用製表符(Tab)進行縮進java

if (true) {
    doSomething();
}
複製代碼

2.行的長度

每行長度不該該超過80個字符.若是一行多於80個字符,應當在一個運算符(逗號,加好等)後換行.下一級應當增長兩級縮進(8個字符).react

// 好的寫法
doSomething(arg1, arg2, arg3, arg4,
        arg5);

// 很差的寫法: 第二行只有4個空格的縮進
doSomething(arg1, arg2, arg3, arg4,
    arg5);
// 很差的寫法: 在運算符以前換行
doSomething(arg1, arg2, arg3, arg4
        ,arg5);
複製代碼

3.原始值

特殊值null除了下述狀況應當避免使用git

  • 用來初始化一個變量,這個變量可能被賦值爲一個對象
  • 用來和一個已經初始化的變量比較,這個變量能夠是也能夠不是一個對象
  • 當函數的參數指望是對象時,被用做返回值傳出
// 好的作法
const person = null;
複製代碼

判斷一個變量是否認義應當使用 typeof 操做符es6

// 好的寫法
if (typeof constiable == 'undefined') {
    // do something
}

// 很差的寫法
if (constiable == 'undefined') {
    // do something
}
複製代碼

4.運算符間距

二元運算符先後必須使用一個空格來保持表達式的整潔.操做符包括賦值運算符和邏輯運算符express

// 好的寫法
const found = (values[i] === item);
// 很差的寫法: 丟失了空格
const found = (values[i]===item);

// 好的寫法
if (found && (count > 10)) {
    doSomething();
}
// 很差的寫法: 丟失了空格
if (found&&(count>10)) {
    doSomething();
}

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

5.括號間距

當使用括號時,緊接左括號以後和緊接右括號以前不該該有空格npm

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

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

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

6.對象直接量

對象直接量應當使用以下格式

  • 起始左花括號應當同表達式保持同一行
  • 每一個屬性的名值對應當保持一個縮進,第一個屬性應當在左花括號後另起一行.
  • 每一個屬性的名值對應當使用不含引號的屬性名,其後緊跟一個冒號(以前不含空格),然後是值
  • 假若屬性值是函數類型,函數體應當在屬性名之下另起一行,並且其先後均應保留一個空行
  • 一組相關的屬性先後能夠插入空行以提升代碼的可讀性
  • 結束的右花括號應當獨佔一行
// 好的寫法
const object = {

    key1: value1,
    key2: value2,

    func: function() {

    },

    key3: value3,
};

// 很差的寫法: 不恰當的縮進
const object = {
        key1: value1,
        key2: value2,
    };

// 很差的寫法:函數體缺乏空行
const object = {

    key1: value1,
    key2: value2,
    func: function() {

    },
    key3: value3,
};
複製代碼

當對象字面量做爲函數參數時,若是值是變量,起始花括號應當同函數名在同一行.全部其他先前列出的規則一樣適用

// 好的寫法
doSomething({
    key1: value1,
    key2: value2,
});

// 很差的寫法
doSomething({ key1: value1, key2: value2 });
複製代碼

7.註釋

頻繁地適用註釋有助於他人理解你的代碼.以下狀況應當使用註釋

  • 代碼晦澀難懂
  • 可能被誤認爲錯誤的代碼
  • 必要但不明顯的針對特定瀏覽器的代碼
  • 對於對象,方法或者屬性,生成文檔是有必要的(使用恰當的文檔註釋).

1).單行註釋

使用單行註釋當用來講明一行代碼或者一組代碼.單行註釋可能有三種使用方式

  • 獨佔一行的註釋,用來解釋下一行代碼
  • 在代碼行的尾部的註釋,用來解釋它以前的代碼
  • 多行,用來註釋掉一個代碼塊
// 好的寫法
if (condition) {

    // 若是代碼執行到這裏,則說明經過了全部的安全性檢測
    allowed();
}

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

// 很差的寫法: 錯誤的縮進
if (condition) {

// 若是代碼執行到這裏,則說明經過了全部的安全性檢測
    allowed();
}

// 很差的寫法: 這裏應當用多行註釋
// 接下來的這段代碼很是難, 那麼,讓我詳細的解釋一下
// 1. xxxx
// 2. xxxx
if (condition) {

// 若是代碼執行到這裏,則說明經過了全部的安全性檢測
    allowed();
}
複製代碼

對於代碼行尾單行註釋的狀況,應確保代碼結尾同註釋之間至少一個縮進

// 好的寫法
const result = something + somethingElse; // somethingElse will never be null

// 很差的寫法: 代碼和註釋間沒有足夠的空格
const result = something + somethingElse;// somethingElse will never be null
複製代碼

註釋一個代碼塊時在連續多行使用單行註釋是惟一能夠接受的狀況.多行註釋不該當在這種狀況下使用

// 好的寫法
// if(condition) {
// doSomething();
// }
複製代碼

2).多行註釋

多行註釋應當在代碼須要更多文字去解釋的時候使用.每一個多行註釋都至少有以下三行. 1.首行僅僅包括 /* 註釋開始.該行不該當有其餘文字 2.接下來的行以 * 開頭並保持左對齊.這些行能夠由文字描述 3.最後一行以 */開頭並同先前行保持對齊.也不該當有其餘文字

多行註釋的首行應當保持同它描述代碼的相同層次的縮進.後續的每行應當有一樣層次的縮進並附加一個空格(爲了適當保持 * 字符的對齊).每個多行代碼以前應當預留一個空格

// 好的寫法
if (condition) {

    /* * 若是代碼執行到這裏 * 說明經過了全部的安全性檢測 */
    allowed();
}

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

    /* *若是代碼執行到這裏 *說明經過了全部的安全性檢測 */
    allowed();
}
// 很差的寫法: 錯誤的縮進
if (condition) {

/* * 若是代碼執行到這裏 * 說明經過了全部的安全性檢測 */
    allowed();
}

// 很差的寫法: 代碼尾部註釋不要用多行註釋格式
const result = something + somethingElse; /* somethingElse 不該當取值爲null */
複製代碼

3)註釋聲明

註釋有時候能夠用來給一段代碼聲明額外的信息.這些聲明的格式以單個單詞打頭並緊跟一個雙引號.可以使用的聲明以下

  • TODO: 說明代碼還未完成.應當包含下一步要作的事情
  • HACK: 代表代碼實現走了一個捷徑
  • XXX: 說明代碼是有問題的並應當儘快修復
  • FIXME: 說明代碼是有問題的並應當儘快修復.重要性略次於XXX
  • REVIEW: 說明代碼任何可能的改動都須要評審 這些聲明可能在一行或多行註釋中使用,而且應當遵循同通常註釋類型相同的格式規則
// 好的寫法
// TODO: 我但願找到一種更快的方式
doSomething();
// 很差的寫法: 註釋聲明空格不正確
// TODO : 我但願找到一種更快的方式
doSomething();

// 好的寫法
// REVIEW: 有更好的方法嗎?
doSomething();
// 很差的寫法: 代碼和註釋應當保持一樣的縮進
    // REVIEW: 有更好的方法嗎?
doSomething();
複製代碼

8.命名

變量命名應當採用駝峯命名格式,首字母小寫,每一個單詞首字母大寫.變量名的第一個單詞應當是一個名詞(而非動詞)比避免同函數混淆.不要在變量名中使用下劃線

// 好的寫法
const myName = 'Jack';

// 很差的寫法: 大寫字母開頭
const MyName = 'Jack';

// 很差的寫法: 動詞開頭
const getMyName = 'Jack';

// 很差的寫法: 使用下劃線
const my_name = 'Jack';
複製代碼

函數命名應當採用駝峯命名格式.函數名的第一個單詞應當是動詞(而非名詞)來避免同變量混淆.函數名中最好不要使用下劃線.

// 好的寫法
function doSomething() {
    // 代碼
}

// 很差的寫法: 大寫字母開頭
function DoSomething() {
    // 代碼
}
// 很差的寫法: 名詞開頭
function car() {
    // 代碼
}
// 很差的寫法: 使用下劃線
function do_something() {
    // 代碼
}
複製代碼

構造函數--經過new元素安撫建立新對象的函數--也應使用駝峯合適命名,首先首字母大寫.構造函數命名應當以非動詞開頭,由於new表明着建立一個對象實例的操做

// 好的寫法
function MyObject() {

}
// 很差的寫法: 小寫字母開頭
function myObject() {
    
}
// 很差的寫法: 使用下劃線
function My_Object() {
    
}
// 很差的寫法: 動詞開頭
function getMyObject() {
    
}
複製代碼

常量(不會被改變的變量)的命名應當是全部字母大寫,不一樣單詞之間用單個下劃線隔開.ES6中使用const來聲明一個常量

// 好的寫法
const TOTAL_COUNT = 10;
// 很差的寫法
const totalCount = 10;
// 很差的寫法: 混合模式
const total_COUNT = 10;
複製代碼

對象的屬性同變量的命名規範相同.對象的方法同函數的命名規則相同.若是屬性或者方法是私有的,應當在以前加一個下劃線

// 好的寫法
const object = {
    _count: 10,

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

9.賦值

當給變量賦值時,若是右側是含有比較語句的表達式,須要用圓括號包裹

// 好的寫法
const flag = (i < count);

// 很差的寫法:遺漏圓括號
const flag = i < count;
複製代碼

10.等號運算符

使用 === (嚴格相等) 和 !==(嚴格不相等)代替 ==(相等) 和 !=(不等) 來避免弱類型轉換錯誤

// 好的寫法
const same = (a === b);

// 很差的寫法: 使用 == 
const same = (a == b);
複製代碼

11.三元操做符

三元運算符應當僅僅用在條件賦值語句中,而不要做爲if語句的替代品.

// 好的寫法
const value = condition ? value1 : value2;

// 很差的寫法: 沒有賦值,應當使用 if 表達式
condition ? doSomething() : doSomethingElse();
複製代碼

12.語句

簡單語句

每一行最多隻包含一條語句.全部簡單的語句都應該以分號(;)結束.

// 好的寫法
const a = 1;
const b = 2;
const c = a + b;

// 很差的寫法: 多個表達式寫在一行
const a = 1;const b = 2;const c = a + b;
複製代碼

返回語句

返回語句當返回一個值的時候不該當使用圓括號包裹,除非在某些狀況下這麼作可讓返回值更容易理解.例如:

return;
return collection.size();
return (size > 0 ? size : defaultSize)
複製代碼

複合語句

複合語句是大括號括起來的語句列表;

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

if語句

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 (initialization; condition; update) {
    statements
}

for (constiable in object) {
    statements
}
複製代碼

當使用 for-in 語句時,記得使用 hasOwnProperty() 進行雙重檢查來過濾出對象的成員

while語句

while (condition) {
    statements
}
複製代碼

do語句

do {
    statements
} while (condition)
複製代碼

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('this should not happen');
}
複製代碼

try語句

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

13.嚴格模式

嚴格模式應當僅限在函數內部使用,千萬不要在全局使用.

ES6 的模塊自動採用嚴格模式,無論你有沒有在模塊頭部加上"use strict";。

14.變量聲明

全部的變量在使用前都應事先定義.變量定義應放在函數開頭. 變量定義前應當初始化,而且賦值操做符應當保持一致的縮進.初始化的變量應當在未初始化變量以前.

推薦使用ES6的letconst來聲明變量

15.函數聲明

函數聲明應當在使用前提早定義. 一個不是做爲方法的函數(也就是沒有做爲一個對象的屬性)應當使用函數定義的格式(不是函數表達式和Function構造器格式). 函數名和開始圓括號以前不該當有空格.結束的圓括號和右邊的花括號之間應該留一個空格.右側的花括號應當同function關鍵字保持同一行.開始和結束括號之間不該該有空格.參數名之間應當在逗號以後保留一個空格.函數體應當保持一級縮進

// 好的寫法
function doSomething(arg1, agr2) {
    return arg1 + arg2;
}
// 很差的寫法: 第一行不恰當的空格
function doSomething (arg1, agr2) {
    return arg1 + arg2;
}
// 很差的寫法: 
const doSomething = function doSomething(arg1, agr2) {
    return arg1 + arg2;
}
// 很差的寫法: 左側的花括號位置不對
function doSomething(arg1, agr2) {
    return arg1 + arg2;
}
// 錯誤的寫法: 使用Function構造器
const doSomething = new Function('arg1', 'agr2', 'return arg1 + arg2');
複製代碼

16.留白

在邏輯相關的代碼塊之間添加空行能夠提升代碼的可讀性

兩行空行權限在以下狀況使用

  • 在不一樣的源代碼文件之間
  • 在類和接口定義之間

單行空行權限在以下狀況使用

  • 方法之間
  • 方法中局部變量和第一行語句之間
  • 多行或單行註釋以前
  • 方法中邏輯代碼塊之間以提升代碼的可讀性

空格應當在以下狀況中使用

  • 關鍵詞後跟括號的狀況應當用空格隔開
  • 參數列表中逗號以後應當保留一個空格
  • 全部的除了點(.)以外的二元運算符,其操做數都應當用空格隔開.單目運算符的操做數之間不該該用空白隔開,諸如一元減號,遞增(++),遞減(--)
  • for語句中的表達式之間應當用空格隔開

17. 須要避免的

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

使用工具(eslint)來強制約束

eslint 規則

eslint規則在.eslintrc.js中定義,以爲不合理的能夠禁掉某條規則,或者有好的建議的也能夠添加; 主要注意一下幾條:

  • 代碼縮進用4空格
  • 語句必須默認後加分號
  • 使用單引號
  • 提交代碼前將console.log語句刪掉或註釋掉(否則影響其餘開發人員調試)
  • 禁止使用const,使用es6的let,const聲明變量

還有一些狀況是不須要檢測的,例如第3方的庫, 框架、組件、ui庫等等,能夠將這些文件放在.eslintignore文件中,能夠忽略eslint的檢測

在文件頂部加上下面這行,能夠禁掉整個文件的eslint規則

/* eslint-disable */
複製代碼

pre-commit

代碼提交以前會強制code-review,不符合規範的不容許提交代碼 使用方法 1.在命令行安裝

npm i --save-dev pre-commit
複製代碼

2.在package.json中配置

{
    "scripts": {
        "eslint": "eslint ./ --ext js,vue --ignore-pattern .eslintignore --cache --fix",
        "lint-message": "echo '開始 eslint 檢查, 存在 error 則會拒絕提交'"
    },
    "pre-commit": [
        "lint-message",
        "eslint" // 進行eslint檢查並自動修復一些簡單的格式錯誤
    ],
}

複製代碼

代碼提交以前會強制code-review,不符合規範的不容許提交代碼

若是項目實在沒時間去改的話,能夠 git commit -m 'XXX' --no-verify 或 git commit -n 'xxx'強制提交

小技巧-vscode能夠配置保存自動修復eslint錯誤

vscode安裝eslint插件,在配置中配置以下

{
     "eslint.autoFixOnSave": true,
     "eslint.enable": true,
     "eslint.options": {
        "extensions": [".js", ".vue", ".jsx"]
     },
     "eslint.validate": [
          {

              "language": "vue",
              "autoFix": true
          },
          {
              "language": "javascript",
              "autoFix": true
          },
          {
              "language": "javascriptreact",
              "autoFix": true
          }
      ],
}

複製代碼

配置完成以後,每次保存,都會自動根據 .eslintrc.js文件自動修復空格,分號的錯誤;可是最好仍是在日常的編碼中養成一個良好的習慣,而不是依賴工具.

下列參考給出的文章及書籍,有時間必定要好好看一下,會幫助你們深入理解JavaScript編碼風格的重要性。永遠記住,規範能解決大部分問題。

參考

相關文章
相關標籤/搜索