基本的格式化
命名
“計算機科學只存在兩個難題:緩存失效和命名。”—— Phil Karlton
只要是書寫代碼,都會涉及變量和函數(shù),因此變量和函數(shù)命名對于增強代碼可讀性至關重要。JavaScript 語言的核心 ECMAScript,即是遵照了駝峰式大小寫命名法:小寫字母開始,后續(xù)每個單詞首字母都大寫。
var thisIsMyName;
var doSomething;
【注意】:駝峰式大小寫分為小駝峰式(Camel Case),以及大駝峰式(Pascal Case)。上面所舉例子就是小駝峰式,而大駝峰式是首字母大寫。
- Google、SproutCore 編程風格指南以及 Dojo 編程風格:推薦使用小駝峰式命名法。
在 2000 年左右,流行另外一種命名方法——匈牙利命名法。名字之前冠以類型標識符前綴,比如 sName 表示字符串,iCounnt 表示整數(shù)。不過這種風格已經是明日黃花風光不再,當前主流的編程規(guī)范都不推薦這種命名法。
變量和函數(shù)
變量名以及函數(shù)名都應當總是遵守駝峰大小寫命名法。變量名前綴應當是名詞,而函數(shù)名前綴應當是動詞。
// 好的寫法
var count = 10;
var myName = "Spirit";
var found = true;
// 不好的寫法:變量看起來像函數(shù)
var getCount = 10;
var isFount = true;
// 好的寫法
function getName() {
return myName;
}
// 不好的寫法:函數(shù)看起來像變量
function theName() {
return myName;
}
【建議】:
- 命名長度應該盡可能短,并抓住要點;
- 盡量在變量名中體現(xiàn)出值的數(shù)據(jù)類型;
- 避免使用沒有意義的命名。
對于函數(shù)和方法命名來說,第一個單詞應該是動詞,這里有一些使用動詞常見的約定。
| 動詞 | 含義 |
|---|---|
| can | 函數(shù)返回一個布爾值 |
| has | 函數(shù)返回一個布爾值 |
| is | 函數(shù)返回一個布爾值 |
| get | 函數(shù)返回一個非布爾值 |
| set | 函數(shù)用來保存一個值 |
if(isEnabled()) {
setName("Spirit");
}
if(getName() === "Spirit") {
doSomething();
}
盡管這些函數(shù)命名細則并沒有被歸納入當下流行的編程風格中,但在很多流行的庫中,JavaScript 開發(fā)者會發(fā)現(xiàn)存在不少這種“偽標準”(pseudostandard)。
jQuery 沒有遵循這種函數(shù)命名約定,一部分在于 jQuery 中方法的使用方式,很多方法同時用作 getter 和 setter。盡管如此,還是推薦使用動詞作為函數(shù)名前綴。
常量:
在 ECMAScript 6 之前,JavaScript 中并沒有真正的常量概念。然而,這并不能阻止開發(fā)者將變量用作常量。為了區(qū)分普通的變量和常量,一種通用的命名約定應運而生。
// 使用大寫字母和下劃線來命名,下劃線用以分隔單詞
var MAX_COUNT = 10;
var URL = "http://www.baidu.com";
構造函數(shù):
在 JavaScript 中,構造函數(shù)只不過是前面冠以 new 運算符的函數(shù)(在 ES6 之前),用來創(chuàng)建對象。
JavaScript 語言本身已經包含了許多內置構造函數(shù),比如 Object 和 RegExp,同樣開發(fā)者也可以創(chuàng)建自己的構造函數(shù)來生成新類型。
【推薦】:構造函數(shù)的命名遵照大駝峰式命名法。
// 好的做法
function Person(name) {
this.name = name;
}
Person.prototype.sayName = function () {
alert(this.name);
};
var me = new Person("spirit");
// 不正確的寫法
var me = Person("Spirit");
【說明】:Crockford 編程規(guī)范、Google 的 JavaScript 風格指南以及 Dojo 編程風格指南都推薦這種實踐。如果構造函數(shù)的首字母不是大寫的,或者構造函數(shù)之前沒有 new 運算符,JSLint 都會給出警告。而 JSHint 只有開啟 newcap 選項后,才會對首字母不是大寫的構造函數(shù)給出警告。
直接量(字面量)
JavaScript 中包含一些類型的原始值:字符串、數(shù)字、布爾值、null 和 undefined。同樣也包含對象直接量和數(shù)組直接量。這其中,只有布爾值是自解釋(self-explanatory)的,其他的類型或多或少都需要思考一下它們如何才能更精確地表示出來。
字符串:
在 JavaScript 中,字符串是獨一無二的。字符串可以用雙引號括起來,也可以用單引號括起來。
var name = "Spirit, \"Hello!\"";
var name2 = 'Spirit, "Hello!"';
和 Java、PHP 這些語言不同,使用單引號括起字符串和雙引號括起字符串在功能上并無不同。除了內部出現(xiàn)字符串界定符(string delimiter)時需要轉義之外,兩種做法在功效上完全一致。我們需要關心的是,代碼從頭到尾保持一種風格。
- Crockford 編程規(guī)范:雙引號。
- jQuery 核心風格指南:雙引號。
- Google:單引號。
【注意】:創(chuàng)建多行字符串時,請使用字符串連接符(+)。
// 非法的 JavaScript 語法,但能在 JS 引擎中正常工作
var longStr = "Here's the story, of a man \
named Spirit.";
// 好的寫法
var longStr = "Here's the story, of a man" +
" named Spirit.";
數(shù)字:
在 JavaScript 中的數(shù)字類型只有一種,因為所有數(shù)字形式——整數(shù)和浮點數(shù)——都存儲為相同的數(shù)據(jù)類型。
有一些數(shù)字直接量格式來表示不同的數(shù)據(jù)格式,其中大部分寫法都很好用,但也有一些寫法有問題。
// 整數(shù)
var count = 10;
// 小數(shù)
var price = 10.0;
var price = 10.00;
// 不推薦的寫法:沒有小數(shù)部分
var price = 10.;
// 不推薦的寫法:沒有整數(shù)部分
var price = .1;
// 不推薦的寫法:八進制寫法已經被棄用了
var num = 010;
// 十六進制寫法
var num = 0xA2;
// 科學計數(shù)法
var num = 1e23; // 等價于 10 的23次方
小數(shù)的寫法請盡量不要省略小數(shù)以及整數(shù)部分。因為這存在一個問題:很難搞清楚是不小心丟掉了還是刻意為之。為了避免歧義,盡量將其書寫完整。
長久以來,JavaScript 支持八進制數(shù)字寫法是很多錯誤和歧義的根源。數(shù)字直接量 010 不是表示 10,而是表示八進制中的 8。大多數(shù)開發(fā)者對八進制格式并不熟悉,也很少用到,所以最好的做法是在代碼中禁止八進制直接量。
null:
null 是一個特殊值,容易將其和 undefined 搞混。我們需要明確在什么場景下使用 null:
- 用來初始化一個變量,這個變量可能賦值為一個對象。
- 用來和一個已經初始化的變量比較,這個變量可以是也可以不是一個對象。
- 當函數(shù)的參數(shù)期望是對象時,用作參數(shù)傳入。
- 當函數(shù)的返回值期望是對象時,用作返回值傳出。
不應當使用 null 的場景:
- 不要使用 null 來檢測是否傳入了某個參數(shù)。
- 不要用 null 來檢測一個未初始化的變量。
// 好的用法
var person = null;
function getPerson() {
if(condition) {
return new Person("Spirit");
} 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();
}
}
理解 null 最好的方式是將它當做對象的占位符。
undefined:
undefined 是一個特殊值。其中一個令人困惑之處在于 null == undefined 的結果是 true。然而,這兩個值的用途卻各不相同。那些沒有被初始化的變量都有一個初始值,即 undefined,表示該變量等待被賦值。
// 不好的寫法
var person;
console.log(person === undefined); // true
盡管這段代碼能正常工作,但建議還是避免在代碼中使用 undefined。因為這個值常常和返回 undefined 的 typeof 運算符混淆。不管是值為 undefined 的變量以及未聲明的變量,typeof 運算符返回的結果都為 undefined。
// foo 未被聲明
var person;
console.log(typeof person); // undefined
console.log(typeof foo); // undefined
也就是說無法區(qū)分值為 undefined 的變量以及未聲明的變量。
【問】如何解決這個會產生歧義的問題呢?
【答】通過禁止使用 undefined,可以有效確保只在一種情況下(未聲明變量)typeof 返回 undefined。禁止使用 undefined 意味著我們要將未賦值的變量都賦予初值。
對象直接量:
創(chuàng)建對象最流行的一種做法是使用對象直接量,在直接量中直接寫出所有屬性,這種方式可以取代先顯式地創(chuàng)建 Object 的實例然后添加屬性的這種做法。
對象直接量允許你將所有的屬性都括在一對花括號內。當定義對象直接量時,常常在第一行包含左花括號,每一個屬性的鍵值對都獨占一行,并保持一個縮進,最后右花括號也獨占一行。
// 不好的寫法
var book = new Object();
book.title = "Database";
book.author = "spirit";
// 好的寫法
var book = {
title : "Database",
author : "Spirit"
}
盡管沒有歸納入文檔中,Google 以及 Crockford 編程規(guī)范推薦使用這種寫法。
數(shù)組直接量:
使用兩個方括號將數(shù)組初始元素括起來,來替代使用 Array 構造函數(shù)的方式。
// 不好的寫法
var colors = new Array("red", "green", "blue");
var numbers = new Array(1, 2, 3, 4);
// 好的寫法
var colors = ["red", "green", "blue"];
var numbers = [1, 2, 3, 4];
Google 以及 Crockford 編程規(guī)范推薦這種寫法。