Douglas Crockford是Javascript權威杜顺,Json格式就是他的發(fā)明疹娶。
去年11月他有一個演講(Youtube)戳晌,談到了好的Javascript編程風格是什么诈闺。
我非常推薦這個演講唠倦,它不僅有助于學習Javascript愿吹,而且能讓你心情舒暢不从,因為Crockford講得很幽默,時不時讓聽眾會心一笑犁跪。
下面椿息,我根據(jù)這個演講和Crockford編寫的代碼規(guī)范,總結一下"Javascript編程風格"坷衍。
所謂"編程風格"(programming style)寝优,指的是編寫代碼的樣式規(guī)則。不同的程序員枫耳,往往有不同的編程風格乏矾。
有人說,編譯器的規(guī)范叫做"語法規(guī)則"(grammar)迁杨,這是程序員必須遵守的钻心;而編譯器忽略的部分,就叫"編程風格"(programming style)铅协,這是程序員可以自由選擇的捷沸。這種說法不完全正確,程序員固然可以自由選擇編程風格狐史,但是好的編程風格有助于寫出質(zhì)量更高痒给、錯誤更少、更易于維護的程序骏全。
所以苍柏,有一點應該明確,"編程風格"的選擇不應該基于個人愛好姜贡、熟悉程度试吁、打字工作量等因素,而要考慮如何盡量使代碼清晰易讀楼咳、減少出錯熄捍。你選擇的律秃,不是你喜歡的風格,而是一種能夠清晰表達你的意圖的風格治唤。這一點,對于Javascript這種語法自由度很高糙申、設計不完全成熟的語言尤其重要宾添。
一、大括號的位置
絕大多數(shù)的編程語言柜裸,都用大括號({})表示區(qū)塊(block)缕陕。起首的大括號的位置,有許多不同的寫法疙挺。
最流行的有兩種扛邑。一種是起首的大括號另起一行:
block
{
...
}
另一種是起首的大括號跟在關鍵字的后面:
block {
...
}
一般來說,這兩種寫法都可以接受铐然。但是蔬崩,Javascript要使用后一種,因為Javascript會自動添加句末的分號搀暑,導致一些難以察覺的錯誤沥阳。
return
{
key:value;
};
上面的代碼的原意,是要返回一個對象自点,但實際上返回的是undefined桐罕,因為Javascript自動在return語句后面添加了分號。為了避免這一類錯誤桂敛,需要寫成下面這樣:
return {
key : value;
};
因此功炮,
規(guī)則1:表示區(qū)塊起首的大括號,不要另起一行术唬。
二薪伏、 圓括號
圓括號(parentheses)在Javascript中有兩種作用,一種表示調(diào)用函數(shù)碴开,另一種表示不同的值的組合(grouping)毅该。我們可以用空格,區(qū)分這兩種不同的括號潦牛。
規(guī)則2:調(diào)用函數(shù)的時候眶掌,函數(shù)名與左括號之間沒有空格。
規(guī)則3:函數(shù)名與參數(shù)序列之間巴碗,沒有空格朴爬。
規(guī)則4:所有其他語法元素與左括號之間,都有一個空格橡淆。
按照上面的規(guī)則召噩,下面的寫法都是不規(guī)范的:
foo (bar)
return(a+b);
if(a === 0) {...}
function foo (b) {...}
function(x) {...}
三母赵、分號
分號表示語句的結束。大多數(shù)情況下具滴,如果你省略了句尾的分號凹嘲,Javascript會自動添加。
var a = 1
等同于
var a = 1;
因此构韵,有人提倡省略句尾的分號周蹭。但麻煩的是,如果下一行的第一個字元(token)是下面這五個字符之一疲恢,Javascript將不對上一行句尾添加分號:"("凶朗、"["、"/"显拳、"+"和"-"棚愤。
x = y
(function (){
...
})();
上面的代碼等同于
x = y(function (){...})();
因此,
規(guī)則5:不要省略句末的分號杂数。
四宛畦、with語句
with可以減少代碼的書寫,但是會造成混淆耍休。
with (o) {
foo = bar;
}
上面的代碼刃永,可以有四種運行結果:
o.foo = bar;
o.foo = o.bar;
foo = bar;
foo = o.bar;
這四種結果都可能發(fā)生,取決于不同的變量是否有定義羊精。因此斯够,
規(guī)則6:不要使用with語句。
五喧锦、相等和嚴格相等
Javascript有兩個表示"相等"的運算符:"相等"(==)和"嚴格相等"(===)读规。
因為"相等"運算符會自動轉(zhuǎn)換變量類型,造成很多意想不到的情況:
0 == ''// true
1 == true // true
2 == true // false
0 == '0' // true
false == 'false' // false
false == '0' // true
" \t\r\n " == 0 // true
因此燃少,
規(guī)則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;
因此虽填,
規(guī)則8:不要將不同目的的語句丁恭,合并成一行。
七斋日、變量聲明
Javascript會自動將變量聲明"提升"(hoist)到代碼塊(block)的頭部牲览。
if (!o) {
var o = {};
}
等同于
var o;
if (!o) {
o = {};
}
為了避免可能出現(xiàn)的問題,不如把變量聲明都放在代碼塊的頭部恶守。
for (var i ...) {...}
最好寫成:
var i;
for (i ...) {...,}
因此竭恬,
規(guī)則9:所有變量聲明都放在函數(shù)的頭部。
規(guī)則10:所有函數(shù)都在使用之前定義熬的。
八、全局變量
Javascript最大的語法缺點赊级,可能就是全局變量對于任何一個代碼塊押框,都是可讀可寫。這對代碼的模塊化和重復使用理逊,非常不利拙绊。
規(guī)則11:避免使用全局變量春锋;如果不得不使用,用大寫字母表示變量名,比如UPPER_CASE隅居。
九、new命令
Javascript使用new命令柑司,從建構函數(shù)生成一個新對象踊餐。
var o = new myObject();
這種做法的問題是,一旦你忘了加上new欲侮,myObject()內(nèi)部的this關鍵字就會指向全局對象崭闲,導致所有綁定在this上面的變量,都變成全部變量威蕉。
規(guī)則12:不要使用new命令刁俭,改用Object.create()命令。
如果不得不使用new韧涨,為了防止出錯牍戚,最好在視覺上把建構函數(shù)與其他函數(shù)區(qū)分開來。
規(guī)則13:建構函數(shù)的函數(shù)名虑粥,采用首字母大寫(InitialCap)如孝;其他函數(shù)名,一律首字母小寫舀奶。
十暑竟、自增和自減運算符
自增(++)和自減(--)運算符,放在變量的前面或后面,返回的值不一樣但荤,很容易發(fā)生錯誤罗岖。
事實上,所有的++運算符都可以用"+= 1"代替腹躁。
++x
等同于
x += 1;
代碼變得更清晰了桑包。有一個很可笑的例子,某個Javascript函數(shù)庫的源代碼中出現(xiàn)了下面的片段:
++x;
++x;
這個程序員忘了纺非,還有更簡單哑了、更合理的寫法:
x += 2;
因此,
規(guī)則14:不要使用自增(++)和自減(--)運算符烧颖,用+=和-=代替弱左。
十一、區(qū)塊
如果循環(huán)和判斷的代碼體只有一行炕淮,Javascript允許該區(qū)塊(block)省略大括號拆火。
下面的代碼
if (a) b(); c();
原意可能是
if (a) { b(); c();}
但是,實際效果是
if (a) { b();} c();
因此涂圆,
規(guī)則15:總是使用大括號表示區(qū)塊们镜。
本文轉(zhuǎn)載于阮一峰blog -- Javascript編程風格。