通用約定
通用約定
註解
原則
- #As short as possible(如無必要,勿增註):盡量提高程式碼本身的清晰性、可讀性。
- As long as necessary(如有必要,盡量詳盡):合理的註解、空行排版等,可以讓程式碼更容易閱讀、更有美感。
單行註解
#必須獨佔一行。 //
後面跟著一個空格,縮排與下一行被註解說明的程式碼一致。
多行註解
避免使用 /*...*/
這樣的多行註解。有多行註解內容時,使用多個單行註解。
函數/方法註解
- 函數/方法註解必須包含函數說明,有參數和傳回值時必須使用註解標識。 ;
- 參數和傳回值註解必須包含類型資訊和說明;
- 當函數是內部函數,外部不可存取時,可以使用@inner 來識別;
/** * 函数描述 * * @param {string} p1 参数1的说明 * @param {string} p2 参数2的说明,比较长 * 那就换行了. * @param {number=} p3 参数3的说明(可选) * @return {Object} 返回值描述 */ function foo(p1, p2, p3) { var p3 = p3 || 10; return { p1: p1, p2: p2, p3: p3 }; }
檔案註解
檔案註解用來告訴不熟悉這段程式碼的讀者這個檔案包含哪些東西。 應該提供文件的大體內容, 它的作者, 依賴關係和兼容性資訊。如下:
/** * @fileoverview Description of file, its uses and information * about its dependencies. * @author user@meizu.com (Firstname Lastname) * Copyright 2009 Meizu Inc. All Rights Reserved. */
命名
變數, 使用 Camel 命名法。
var loadingModules = {};
私有屬性、變數和方法以下劃線 _ 開頭。
var _privateMethod = {};
常數, 使用全部字母大寫,單字間底線分隔的命名方式。
var HTML_ENTITY = {};
- 函數, 使用 Camel 命名法。
- 函數的參數, 使用 Camel 命名法。
function stringFormat(source) {} function hear(theBells) {}
- 類別, 使用Pascal 命名法
- 類別的 方法/ 屬性, 使用Camel 命名法
function TextNode(value, engine) { this.value = value; this.engine = engine; } TextNode.prototype.clone = function () { return this; };
- 枚舉變數 使用Pascal 命名法。
- 列舉的屬性, 使用全部字母大寫,單字間底線分隔的命名方式。
var TargetState = { READING: 1, READED: 2, APPLIED: 3, READY: 4};
由多個單字組成的 縮寫單字,在命名中,根據當前命名法和出現的位置,所有字母的大小寫與首字母的大小寫保持一致。
function XMLParser() {} function insertHTML(element, html) {} var httpRequest = new HTTPRequest();
命名語法
類別名稱,使用名詞。
function Engine(options) {}
函數名稱,使用動賓片語。
function getStyle(element) {}
boolean 類型的變數使用 is 或 has 開頭。
var isReady = false;var hasMoreCommands = false;
Promise 物件用動賓短語的進行式表達。
var loadingData = ajax.get('url'); loadingData.then(callback);
介面命名規格
- 可讀性強,見名曉義;
- 盡量不與jQuery 社群已有的習慣衝突;
- 盡量寫全。不用縮寫,除非是下面列表中約定的;(變數以表達清楚為目標,uglify 會完成壓縮體積工作)
True 和False 布林表達式
類型偵測優先使用typeof。物件類型檢測使用 instanceof。 null 或 undefined 的檢測使用 == null。
下面的布林表達式都會回傳false:
- null
- undefined
- '' 空字串
- 0數字0
但小心下面的, 可都回傳true:
- '0' 字串0
- [] 空數組
- {} 空物件
不要在Array 上使用for-in 迴圈
for-in 迴圈只用於 object/map/hash
的遍歷, 對 Array
用for-in 循環有時會出錯. 因為它並不是從0 到length - 1 進行遍歷, 而是所有出現在物件及其原型鏈的鍵值。
// Not recommended function printArray(arr) { for (var key in arr) { print(arr[key]); } } printArray([0,1,2,3]); // This works. var a = new Array(10); printArray(a); // This is wrong. a = document.getElementsByTagName('*'); printArray(a); // This is wrong. a = [0,1,2,3]; a.buhu = 'wine'; printArray(a); // This is wrong again. a = new Array; a[3] = 3; printArray(a); // This is wrong again. // Recommended function printArray(arr) { var l = arr.length; for (var i = 0; i < l; i++) { print(arr[i]); } }
二元和三元運算子
運算子總是寫在前一行, 以免分號的隱式插入產生預想不到的問題。
var x = a ? b : c; var y = a ? longButSimpleOperandB : longButSimpleOperandC; var z = a ? moreComplicatedB : moreComplicatedC;
.
運算子也是如此:
var x = foo.bar(). doSomething(). doSomethingElse();
條件(三元)運算子(?:)
三元運算子用於取代if 條件判斷語句。
// Not recommended if (val != 0) { return foo(); } else { return bar(); } // Recommended return val ? foo() : bar();
&& 和 ||
二元布林運算子是可短路的, 只有在必要時才會計算到最後一項。
// Not recommended function foo(opt_win) { var win; if (opt_win) { win = opt_win; } else { win = window; } // ... } if (node) { if (node.kids) { if (node.kids[index]) { foo(node.kids[index]); } } } // Recommended function foo(opt_win) { var win = opt_win || window; // ... } var kid = node && node.kids && node.kids[index]; if (kid) { foo(kid); }