天天看點

【薦】JavaScript編碼風格

作者:阮一峰

Douglas Crockford是 JavaScript 權威,Json 格式就是他的發明。

去年 11 月他有一個演講(Youtube),談到了好的 JavaScript 程式設計風格是什麼。

【薦】JavaScript編碼風格

我非常推薦這個演講,它不僅有助于學習 JavaScript,而且能讓你心情舒暢,因為 Crockford 講得很幽默,時不時讓聽衆會心一笑。

下面,我根據這個演講和 Crockford 編寫的​​代碼規範​​,總結一下"JavaScript 程式設計風格"。

【薦】JavaScript編碼風格

所謂"程式設計風格"(programming style),指的是編寫代碼的樣式規則。不同的程式員,往往有不同的程式設計風格。

有人說,編譯器的規範叫做"文法規則"(grammar),這是程式員必須遵守的;而編譯器忽略的部分,就叫"程式設計風格" (programming style),這是程式員可以自由選擇的。這種說法不完全正确,程式員固然可以自由選擇程式設計風格,但是好的程式設計風格有助于寫出品質更高、錯誤更少、更易于 維護的程式。

是以,有一點應該明确,"程式設計風格"的選擇不應該基于個人愛好、熟悉程度、打字工作量等因素,而要考慮如何盡量使代碼清晰易讀、減少出錯。你選 擇的,不是你喜歡的風格,而是一種能夠清晰表達你的意圖的風格。這一點,對于 JavaScript 這種文法自由度很高、設計不完全成熟的語言尤其重要。

【薦】JavaScript編碼風格

一、大括号的位置

絕大多數的程式設計語言,都用大括号({})表示區塊(block)。起首的大括号的位置,有許多不同的​​寫法​​。

最流行的有兩種。一種是起首的大括号另起一行:

block
{
    ...
}      

另一種是起首的大括号跟在關鍵字的後面:

block {
    ...
}      

一般來說,這兩種寫法都可以接受。但是,JavaScript 要使用後一種,因為 JavaScript 會自動添加句末的分号,導緻一些難以察覺的錯誤。

return
{
    key:value;
};      

上面的代碼的原意,是要傳回一個對象,但實際上傳回的是 undefined,因為 JavaScript 自動在 return 語句後面添加了分号。為了避免這一類錯誤,需要寫成下面這樣:

return {
    key : value;
};      

是以,

規則1:表示區塊起首的大括号,不要另起一行。

二、 圓括号

圓括号(parentheses)在 JavaScript 中有兩種作用,一種表示調用函數,另一種表示不同的值的組合(grouping)。我們可以用空格,區分這兩種不同的括号。

規則2:調用函數的時候,函數名與左括号之間沒有空格。規則3:函數名與參數序列之間,沒有空格。規則4:所有其他文法元素與左括号之間,都有一個空格。

按照上面的規則,下面的寫法都是不規範的:

foo (bar)
return(a+b);
if(a === 0) {...}
function foo (b) {...}
function(x) {...}      
【薦】JavaScript編碼風格

三、分号

分号表示語句的結束。大多數情況下,如果你省略了句尾的分号,JavaScript 會自動添加。

var a = 1      

等同于

var a = 1;      

是以,有人​​提倡​​省略句尾的分号。但麻煩的是,如果下一行的第一個字元(token)是下面這五個字元之一,JavaScript 将不對上一行句尾​​添加分号​​:"("、"["、"/"、"+"和"-"。

x = y
(function (){
    ...
})();      

上面的代碼等同于

x = y (function (){...})();      
規則5:不要省略句末的分号。

四、with 語句

with 可以減少代碼的書寫,但是會造成混淆。

with (o) {
    foo = bar;
}      

上面的代碼,可以有四種運作結果:

o.foo = bar;
o.foo = o.bar;
foo = bar;
foo = o.bar;      

這四種結果都可能發生,取決于不同的變量是否有定義。是以,

規則6:不要使用 with 語句。
【薦】JavaScript編碼風格

五、相等和嚴格相等

JavaScript 有兩個表示"相等"的運算符:"相等"(==)和"嚴格相等"(===)。

因為"相等"運算符會自動轉換變量類型,造成很多意想不到的情況:

0 == '' // true
1 == true // true
2 == true // false
0 == '0' // true
false == 'false' // false
false == '0' // true
"   
 " == 0 // true      
規則7:不要使用"相等"(==)運算符,隻使用"嚴格相等"(===)運算符。

六、語句的合并

有些程式員追求簡潔,喜歡合并不同目的的語句。比如,原來的語句是

a = b;
if (a) {...}      

他喜歡寫成下面這樣:

if (a = b) {...}      

雖然語句少了一行,但是可讀性大打折扣,而且會造成誤讀,讓别人誤以為這行代碼的意思是:

if (a === b){...}      

另外一種情況是,有些程式員喜歡在同一行中指派多個變量:

var a = b = 0;      

他以為,這行代碼等同于:

var a = 0, b = 0;      

實際上不是,它的真正效果是下面這樣:

b = 0;
var a = b;      
規則8:不要将不同目的的語句,合并成一行。
【薦】JavaScript編碼風格

七、變量聲明

JavaScript 會自動将變量聲明"提升"(hoist)到代碼塊(block)的頭部。

if (!o) {
    var o = {};
}      
var o;
if (!o) {
    o = {};
}      

為了避免可能出現的問題,不如把變量聲明都放在代碼塊的頭部。

for (var i ...) {...}      

最好寫成:

var i;
for (i ...) {...,}      
規則9:所有變量聲明都放在函數的頭部。規則 10:所有函數都在使用之前定義。

八、全局變量

JavaScript 最大的文法缺點,可能就是全局變量對于任何一個代碼塊,都是可讀可寫。這對代碼的子產品化和重複使用,非常不利。

規則 11:避免使用全局變量;如果不得不使用,用大寫字母表示變量名,比如 UPPER_CASE。
【薦】JavaScript編碼風格

九、new 指令

JavaScript 使用 new 指令,從建構函數生成一個新對象。

var o = new myObject ();      

這種做法的問題是,一旦你忘了加上 new,myObject ()内部的 this 關鍵字就會指向全局對象,導緻所有綁定在 this 上面的變量,都變成全部變量。

規則 12:不要使用 new 指令,改用 ​​Object.create ()​​指令。

如果不得不使用 new,為了防止出錯,最好在視覺上把建造函數與其他函數區分開來。

規則 13:建構函數的函數名,采用首字母大寫(InitialCap);其他函數名,一律首字母小寫。

十、自增和自減運算符

自增(++)和自減(--)運算符,放在變量的前面或後面,傳回的值不一樣,很容易發生錯誤。

事實上,所有的++運算符都可以用"+= 1"代替。

++x;      
x += 1;      

代碼變得更清晰了。有一個很可笑的例子,某個 JavaScript 函數庫的源代碼中出現了下面的片段:

++x;
++x;      

這個程式員忘了,還有更簡單、更合理的寫法:

x += 2;      
規則 14:不要使用自增(++)和自減(--)運算符,用+=和-=代替。

十一、區塊

如果循環和判斷的代碼體隻有一行,JavaScript 允許該區塊(block)省略大括号。

下面的代碼

if (a) b (); c ();      

原意可能是

if (a) { b (); c ();}      

但是,實際效果是

if (a) { b ();} c ();      
規則 15:總是使用大括号表示區塊。

繼續閱讀