天天看點

JavaScript編碼風格指南(中文版)

程式語言的編碼風格對于一個長期維護的軟體非常重要,特别是在團隊協作中。如果一個團隊使用統一規範的編碼分風格,可以提高團隊的協作水準和工作效率。程式設計風格指南的核心是基本的格式化規則,這些規則決定了如何編寫高水準的代碼。本指南來自于《編寫可維護的JavaScript》這本書,基于"Java語言編碼規範"和Crockford的JavaScript程式設計規範,還有Nicbolas的一些個人經驗和喜好。想了解更多的内容請閱讀《編寫可維護的JavaScript》。

前言:

程式語言的編碼風格對于一個長期維護的軟體非常重要,特别是在團隊協作中。如果一個團隊使用統一規範的編碼分風格,可以提高團隊的協作水準和工作效率。程式設計風格指南的核心是基本的格式化規則,這些規則決定了如何編寫高水準的代碼。本指南來自于《編寫可維護的JavaScript》這本書,基于"Java語言編碼規範"和Crockford的JavaScript程式設計規範,還有Nicbolas的一些個人經驗和喜好。寫作本文旨在加深自己印象,也為了更多人的了解到JS編碼風格,提高自己的編碼品質。想了解更多的内容請閱讀《編寫可維護的JavaScript》。

1.縮進

每一行的層級由4個空格組成,避免使用Tab進行縮進。

1 // 好的寫法
2 if (true) {
3     doSomeThing();
4 }      

2.行的長度

每行長度不應超過80個字元。如果一行超過80個字元,應當在一個運算符後換行。下一行應當增加兩級縮進(8個字元)。

1 // 好的寫法
2 doSomeThing(argument1, argument2, aegument3, argument4,
3         argument5);
4 
5 // 不好的寫法:第二行隻有4個空格的縮進
6 doSomeThing(argument1, argument2, aegument3, argument4,
7     argument5);      

3.原始值

字元串應當始終使用雙引号且保持一行,避免在字元串中使用斜線另起一行。

數字應當使用十進制整數,科學計算法表示整數,十六進制整數,或者十進制浮點小數,小數前後應當至少保留一位數字。避免使用八進制直接量。

特殊值null除了下述情況下應當避免使用。

  • 用來初始化一個變量,這個變量可能被指派為一個對象。
  • 用來和一個已經初始化的變量比較,這個變量可以是也可以不是一個對象。
  • 當函數的參數期望是對象時,被用作參數傳入。
  • 當函數的傳回值期望是對象時,被用作傳回值傳出。

避免使用特殊值undefined。判斷一個變量是否定義應當使用typeof操作符。

4.運算符間距

二進制預算符前後必須使用一個空格來保持表達式的整潔。操作符包括指派運算符和邏輯運算符。

1 // 好的寫法
2 for (var i = 0; i < count; i++) {
3     process(i);
4 }
5 
6 // 不好的寫法:丢失了空格
7 for (var i=0; i<count; i++) {
8     process(i);
9 }      

5.括号間距

當使用括号時,緊接左括号之後和緊接右括号之前不應該有空格。

1 // 好的寫法
2 for (var i = 0; i < count; i++) {
3     process(i);
4 }
5  
6 // 不好的寫法:參數兩邊有額外的空格
7 for (var i = 0; i < count; i++) {
8     process( i );
9 }      

6.對象直接量

對象直接量應當有如下格式。

  • 起始左花括号應當同表達式保持同一行。
  • 每個屬性的名值對應當保持一個縮進,第一個屬性應當在左花括号後另起一行。
  • 每個屬性的名值對應當使用不含引号的屬性名,其後緊跟一個冒号(之前不舍空格),其後是值。
  • 倘若屬性值是函數類型,函數體應當在屬性名之下另起一行,而且其前後均應保留一個空行。
  • 一組相關的屬性前後可以插入空行以提升代碼的可讀性。
  • 結束的右花括号應當獨占一行。
1 // 好的寫法
 2 var object = {
 3 
 4     key1: value1,
 5     key2: value2,
 6 
 7     func: function() {
 8     // doSomeThing
 9     },
10 
11     key3: value3
12 };
13 
14 // 不好的寫法:不恰當的縮進
15 var object = {
16         key1: value1,
17         key2: value2
18     };
19 
20 // 不好的寫法:函數體周圍缺少空行
21 var object = {
22 
23     key1: value1,
24     key2: value2,
25     func: function() {
26     // doSomeThing
27     },
28     key3: value3
29 };      

當對象字面量作為函數參數時,如果值是變量,起始花括号應當同函數名在同一行。所有其餘先前列出的規則同樣适用。

1 // 好的寫法
2 doSomeThing({
3     key1: value1,
4     key2: value2
5 });
6 // 不好的寫法:所有代碼在一行上
7 doSomeThing({ key1: value1, key2: value2 });      

7.注釋

使用簡潔明了注釋有助于他人了解你的代碼。如下情況應當使用注釋。

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

單行注釋

單行注釋應當用來說明一行代碼或者一組相關的代碼。單行注釋可能有三種使用方式。

  • 獨占一行的注釋,用來解釋下一行代碼。
  • 在代碼行的尾部的注釋,用來解釋它之前的代碼。
  • 多行,用來注釋掉一個代碼塊。
1 // 好的寫法
 2 if (condition) {
 3 
 4     // 如果代碼執行到這裡,則表明通過了所有安全檢查
 5     allowed();
 6 }
 7 
 8 // 不好的寫法:注釋之前沒有空行
 9 if (condition) {
10     // 如果代碼執行到這裡,則表明通過了所有安全檢查
11     allowed();
12 }
13 
14 // 不好的寫法:錯誤的縮進
15 if (condition) {
16 
17 // 如果代碼執行到這裡,則表明通過了所有安全檢查
18     allowed();
19 }
20 
21 // 不好的寫法:應當使用多行注釋
22 // 這段代碼進行**判斷
23 // 然後執行
24 if (condition) {
25 
26     // 如果代碼執行到這裡,則表明通過了所有安全檢查
27     allowed();
28 }
29 
30 // 好的寫法:在行尾注釋時,代碼結尾和注釋間應保留一個空格
31 if (condition) {
32 
33     // 如果代碼執行到這裡,則表明通過了所有安全檢查
34     allowed(); // 執行**函數
35 }
36 
37 // 不好的寫法:代碼和注釋間沒有足夠的空格
38 if (condition) {
39 
40     // 如果代碼執行到這裡,則表明通過了所有安全檢查
41     allowed();// 執行**函數
42 }
43 
44 // 好的寫法:在注釋掉一個代碼塊時,應聯系使用單行注釋,多行注釋不應當使用在此種情況下。
45 // if (condition) {
46 //     allowed();//執行**函數
47 // }      

多行注釋

多行注釋應當在代碼需要更多文字去解釋的時候使用。每個多行注釋都至少有如下三行:

  1. 首行僅僅包括/*注釋開始。該行不應當有其他文字。
  2. 接下來的行以*開頭并保持左對齊。這些可以有文字描述。
  3. 最後一行以*/開頭并同先前行保持對齊。也不應有其他文字。

多行注釋的首行應當保持同它描述代碼的相同層次的縮進。後續的每行應當有同樣層次的縮進并附加一個空格(為了适當保持*字元的對齊)。每一個多行代碼之前應當預留一個空行。

1 // 好的寫法、
2 if (condition) {
3 
4     /*
5     * 如果代碼執行到這裡
6     * 說明通過了所有的安全檢測
7     */
8     allowed();
9 }      

注釋聲明

注釋有時候也可以用來給一段代碼聲明額外的資訊。這些聲明的格式以單個單詞打頭并緊跟一個冒号。可以使用的聲明如下。

TODO:說明代碼還未完成。應當包含下一步要做的事情。

HACK:表明代碼實作走了一個捷徑。應當包含為何使用hack的原因。這也可能表明該問題可能會有更好的解決辦法。

XXX:說明代碼是有問題的并應當盡快修複。

FIXME:說明代碼是有問題的并應盡快修複。重要性略次于XXX。

REVIEW:說明代碼在任何可能的改動都需要評審。

這些聲明可能在一行或者多行注釋中使用,并且應當遵循同一般注釋類型相同的格式規則。

8.命名

變量和函數在命名時應當小心。命名應緊限于數字字母字元,某些情況下可以使用下劃線(_)。最好不要在任何命名中使用美元符号($)或者反斜杠(\)。

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

1 // 好的寫法
 2 var accountNumber = "test001";
 3  
 4 // 不好的寫法:大寫字母開頭
 5 var AccountNumber = "test001";
 6 
 7 // 不好的寫法:動詞開頭
 8 var getAccountNumber = "test001";
 9 
10 // 不好的寫法:使用下劃線
11 var account_number = "test001";      

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

1 // 好的寫法
 2 function doSomething() {
 3     // code
 4 }
 5 
 6 // 不好的寫法:大寫字母開頭
 7 function DoSomething() {
 8     // code
 9 }
10 
11 // 不好的寫法:名詞開頭
12 function something() {
13     // code
14 }
15 
16 // 不好的寫法:使用下劃線
17 function do_something() {
18     // code
19 }      

構造函數--通過new運算符建立新對象的函數--也應當以駝峰格式命名并且首字元大寫。構造函數名稱應當以非動詞開頭,因為new代表着建立一個對象執行個體的操作。

1 // 好的寫法
 2 function MyObject() {
 3     // code
 4 }
 5 
 6 // 不好的寫法:小寫字母開頭
 7 function myObject() {
 8     // code
 9 }
10 
11 // 不好的寫法:使用下劃線
12 function my_object() {
13     // code
14 }
15 
16 // 不好的寫法:動詞開頭
17 function getMyObject() {
18     // code
19 }      

常量(值不會被改變的變量)的命名應當是所有大寫字母,不同單詞之間單個下劃線隔開。

1 // 好的寫法
2 var TOTAL_COUNT = 10;
3 
4 // 不好的寫法:駝峰形式
5 var totalCount = 10;
6 
7 // 不好的寫法:混合形式
8 var total_COUNT = 10;      

對象的屬性同變量的命名規則相同。對象的方法同函數的命名規則相同。如果屬性或者方法是私有的,應當在之前加上一個下劃線。

1 // 好的寫法
2 var object = {
3     _count: 10,4 
5     _getCount: function() {
6         return this._count;
7     }
8 }      

9.變量與函數聲明

變量聲明

所有的變量在使用前都應當事先定義。變量定義應當放在函數開頭,使用一個var表達式每行一個變量。除了首行,所有行都應當多一層縮進以使變量名能夠垂直方向對齊。變量定義時應當初始化,并且指派操作符應當保持一緻的縮進。初始化的變量應當在未初始化變量之前。

1 // 好的寫法
2 var count = 10,
3     name = "jeri",
4     found = false,
5     empty;      

函數聲明

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

1 // 好的寫法
 2 function outer() {
 3     var count = 10,
 4         name = "jeri",
 5         found = false,
 6         empty;
 7     function inner() {
 8         // code
 9     }
10     // 調用inner()的代碼
11 }      

匿名函數可能作為方法指派給對象,或者作為其他函數的參數。function關鍵字同開始括号之間不應有空格。

1 // 好的寫法
2 object.method = function() {
3     // code
4 };
5 
6 // 不好的寫法:不正确的空格
7 object.method = function () {
8     // code
9 };      

立即被調用的函數應當在函數調用的外層用園括号包裹。

1 // 好的方法
2 var value = (function() {
3 
4     // 函數體
5 
6     return {
7         message:"hi"
8     }
9 }());      

嚴格模式

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

1 // 不好的寫法:全局使用嚴格模式
 2 "use strict";
 3 
 4 function doSomething() {
 5     // code
 6 }
 7  
 8 // 好的寫法
 9 function doSomething() {
10     "use strict";
11  
12     // code
13 }      

10.運算符

指派

給變量指派時,如果右側是含有比較語句的表達式,需要用圓括号包裹。

1 // 好的寫法
2 var flag = (i < count);
3 
4 // 不好的寫法:遺漏圓括号
5 var flag = i < count;      

等号運算符

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

1 // 好的寫法
2 var same = (a === b);
3 
4 // 好的寫法
5 var same = (a == b);      

三元操作符

三元運算符應當僅僅用在條件指派語句中,而不要作為if語句的替代品。

1 // 好的寫法
2 var value = condition ? value1 : value2;
3 
4 // 不好的寫法:沒有指派,應當使用if表達式
5 condition ? doSomething() : doSomethingElse;      

11.語句

簡單語句

每一行最多隻包含一條語句。所有簡單的語句都應該以分号(;)結束。

1 // 好的寫法
2 count++;
3 a = b;
4 
5 // 不好的寫法:多個表達式寫在一行
6 count++; a = b;      

傳回語句

傳回語句當傳回一個值的時候不應當使用圓括号包裹,除非在某些情況下這麼做可以讓傳回值更容易了解。例如:

1 return;
2 
3 return collection.size();
4 
5 return (size > 0 ? size : defaultSize);      

複合語句

複合語句是大括号括起來的語句清單。

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

if 語句

if 語句應當是下面的格式。

1 if (condition) {
 2     statements
 3 }
 4 
 5 if (condition) {
 6     statements
 7 } else {
 8     statements
 9 }
10 
11 if (condition) {
12     statements
13 } else if (condition) {
14     statements
15 } else {
16     statements
17 }      

絕不允許在if語句中省略花括号。

1 // 好的寫法
 2 if (condition) {
 3     doSomething();
 4 }
 5 
 6 // 不好的寫法:不恰當的空格
 7 if (condition){
 8     doSomething();
 9 }
10 
11 // 不好的寫法:所有代碼都在一行
12 if (condition) { doSomething(); }
13 
14 // 不好的寫法:所有代碼都在一行且沒有花括号
15 if (condition) doSomething();      

for 語句

for類型的語句應當是下面的格式。

1 for (initialization; condition; update) {
2     statements
3 }
4 
5 for (variable in object) {
6     statements
7 }      

for語句的初始化部分不應當有變量聲明。

1 // 好的方法
 2 var i,
 3     len;
 4 
 5 for (i=0, len=0; i < len; i++) {
 6     // code
 7 }
 8 
 9 // 不好的寫法:初始化時候聲明變量
10 for (var i=0, len=0; i < len; i++) {
11     // code
12 }
13 
14 // 不好的寫法:初始化時候聲明變量
15 for (var prop in object) {
16     // code
17 }      

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

while 語句

while 類的語句應當是下面的格式。

1 while (condition) {
2     statements
3 }      

do 語句

do 類的語句應當是下面的格式。

1 do {
2     statements
3 } while (condition);      

switch 語句

switch 類的語句應當是如下格式。

1 switch (expression) {
2     case expression:
3         statements
4 
5     default:
6         statements
7 }      

switch下的第一個case都應當保持一個縮進。除第一個之外包括default在内的每一個case都應當在之前保持一個空行。

每一組語句(除了default)都應當以break、return、throw結尾,或者用一行注釋表示跳過。

1 // 好的寫法
 2 switch (value) {
 3     case 1:
 4         /* falls through */
 5 
 6     case 2:
 7         doSomething();
 8         break;
 9 
10     case 3:
11         return true;
12 
13     default:
14         throw new Error("Some error");
15 }      

如果一個switch語句不包含default情況,應當用一行注釋代替。

1 // 好的寫法
 2 switch (value) {
 3     case 1:
 4         /* falls through */
 5 
 6     case 2:
 7         doSomething();
 8         break;
 9 
10     case 3:
11         return true;
12 
13     default:
14         // 沒有default
15 }      

try 語句

try類的語句應當格式如下。

1 try {
 2     statements
 3 } catch (variable) {
 4     statements
 5 }
 6 
 7 try {
 8     statements
 9 } catch (variable) {
10     statements
11 } finally {
12     statements
13 }      

12.留白

在邏輯相關的代碼之間添加空行代碼可以提高代碼的可讀性。

兩行空行僅限于在如下情況下使用:

  • 在不同的源代碼檔案之間。
  • 在類和接口定義之間。

單行空行僅限在如下情況中使用。

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

空格應當在如下的情況下使用。

  • 關鍵詞後跟括号的情況應當用空格隔開。
  • 參數清單中逗号之後應當保留一個空格。
  • 所有的除了點(.)之外的二進制運算符,其操作數都應當用空格隔開。單目運算符的操作數之間不應該用空白隔開,例如一進制減号,遞增(++),遞減(--)。
  • for 語句的表達式之間應當用空格隔開。

13.需要避免的 

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

寫在最後

  上述指南并不是在開發過程中必須完全遵守的,我們可以隻汲取其中的一部分來改善自己的編碼風格,讓自己的代碼易讀、可維護。關于編碼風格,每個團隊都有自己的特色,隻要保持團隊一緻性,可以高效的開發就OK了。有些規則也并不是我們必須一成不變地遵守的,比如在縮進方面,我們使用Tab鍵很多時候更加地便捷,但是我們不能保證在任何環境下Tab都代表4個空格,為了在縮進方面保持一緻性,如果使用Tab鍵那麼在整個過程中都要使用;還有關于""和‘’的使用,我們也不必都使用"",使用''也是可以的,隻要保持一緻的風格就可以了。還有很多其他類似的風格問題,全憑個人選擇。

  沒有絕對的準則,隻有适不适合。

資料冰冷的,但我們要讓資料溫暖起來,改變我們的生活!

繼續閱讀