編碼規範 1. 縮進 採用2個空格縮進,而不是tab縮進。空格在編輯器中與字元是等寬的,而tab可能因編輯器的設置不同。2個空格會讓代碼看起來緊湊、明快。 2. 變數聲明 永遠用var聲明變數,不加var時會將其變為全局變數,這樣可能會意外污染上下文,或是被意外污染。在ECMAScript5的scr ...
1. 縮進
採用2個空格縮進,而不是tab縮進。空格在編輯器中與字元是等寬的,而tab可能因編輯器的設置不同。2個空格會讓代碼看起來緊湊、明快。
2. 變數聲明
永遠用var聲明變數,不加var時會將其變為全局變數,這樣可能會意外污染上下文,或是被意外污染。在ECMAScript5的scrict模式下,未聲明的變數將會直接拋出ReferenceError異常。
需要說明的是,每行聲明都應該帶上var,而不是只有一個var,示例代碼如下;
1 var assert = require('assert'); 2 var fork = require('child_process').fork; 3 var net = require('net'); 4 var EventEmitter = require('events').EventEmitter;
錯誤的示例如下所示:
1 var assert = require('assert') 2 , fork = require('child_process').fork 3 , net = require('net') 4 , EventEmitter = require('events').EventEmitter;
3. 空格
在操作符前後需要加空格,比如 +、-、*、%、=等操作符前後都應該存在一個空格,示例如下:
1 var foo = 'bar' + baz;
錯誤的示例如下所示:
1 var foo='bar'+baz;
此外,在小括弧的前後應該存在空格,如:
1 if (true) { 2 // some code 3 }
錯誤的示例如下所示:
1 if(true){ 2 // some code 3 }
4. 單雙引號的使用
由於雙引號在別的場景下使用較多,在Node中使用字元串時儘量使用單引號,這樣無需轉義,如:
1 var html = '<a href="http://cnodejs.org">CNode</a>';
而在JSON中,嚴格的規範是要求字元串用雙引號,內容中出現雙引號時,需要轉義。
5. 大括弧的位置
一般情況下,大括弧無需另起一行,如
1 if (true) { 2 // some code 3 }
錯誤的示例如下所示:
1 if (true) 2 { 3 // some code 4 }
6. 逗號
逗號用於變數聲明的分割或是元素的分割。如果逗號不在行結尾,前面需要一個空格。此外逗號不允許出現在行首,比如:
var foo = 'hello', bar = 'world'; // 或是 var hello = { foo: 'hello', bar: 'world' }; // 或是 var world = ['hello', 'world'];
錯誤的示例如下所示:
1 var foo = 'hello' 2 , bar = 'world'; 3 // 或是 4 var hello = {foo: 'hello' 5 , bar: 'world' 6 }; 7 // 或是 8 var world = [ 9 'hello' 10 , 'world' 11 ];
7. 分號
給表達式結尾加根號。儘管Javascript編譯器會自動給行尾添加分號,但還是會帶來一些誤解,示例如下:
1 function add() { 2 var a = 1, b = 2 3 return 4 a + b 5 }
將會得到undefined的返回值。因為自動加入分號會變成如下的樣式:
1 function add() { 2 var a = 1, b = 2; 3 return; 4 a + b; 5 }
後續的a + b將不會執行。
而如下的代碼:
x = y (function () { }()) // 執行時會得到 x = y(function () {}())
由於自動添加分號可能會帶來未預期的結果,所以添加上分號有助於避免誤會。
命名規範
在編碼過程中,命名是重頭戲。好的命名可以令代碼賞心悅目,帶來愉悅的閱讀享受,令代碼具有良好的可維護性。命令的主要範疇有變數、常量、方法、類、文件、包等。
1. 變數命名
變數名都採用小駝峰式命名,即除了第一個單詞的首字母不大寫外,每個單詞的首字母都大寫,詞與詞之間沒有任何特殊符號,如:
1 var adminUser = {};
錯誤的示例如下:
1 var admin_user = {};
2. 方法命名
方法命名與變數命名一樣,採用小駝峰式命名。與變數不同的是,方法名儘量採用動詞或判斷行辭彙,如:
1 var getUser = function () {}; 2 var isAdmin = function () {}; 3 User.prototype.getInfo = function () {};
錯誤的示例如下:
1 var get_user = function () {}; 2 var is_admin = function () {}; 3 User.prototype.get_info = function () {};
3. 類命名
類名採用大駝峰式命名,即所有單詞的首字母都大寫,如:
1 function User(){ 2 }
4. 常量命名
作為常量時,單詞的所有字母都大寫,並用下劃線分割,如:
1 var PINK_COLOR = "pink";
5. 文件命名
命名文件時,請儘量採用下劃線分割單詞,比如child_process.js和string.decode.js。如果你不想將文件暴露給其他用戶,可以約定以下劃線開頭,如_linklist.js
6. 包名
如果你有貢獻模塊並將其打包發佈到NPM上。在包名中,儘量不要包含js或node的字樣,它是重覆的。包名應當適當短且有意義的,如:
1 var express = require('express');
比較操作
在比較操作中,如果是無法容忍的場景,請儘量使用 === 代替 ==,否則你會遇到下麵這河陽不符合邏輯的結果:
1 '0' == 0; // true 2 '' == 0 // true 3 '0' === '' // false
此外,當判斷容忍假值時,可以無需使用 === 或 ==。在下麵的代碼中,當foo是0、undefined、null、false、‘ ’ 時,都會進入分支:
1 if (!foo) { 2 // some code 3 }
字面量
請儘量使用{}、[]代替new Object()、new Array(),不要使用string、bool、number對象類型,即不要使用new String、new Boolean 和 new Number。
作用域
在JavaScript中,需要註意一個關鍵字和一個方法,它們是with和eval(),容易引起作用域混亂。
1. 慎用with
示例代碼如下:
1 with (obj) { 2 foo = bar; 3 }
它的結果有可能是如下四種之一:obj.foo = obj.bar; 、obj.foo = bar;、 foo = bar;、 foo = obj.bar;,這些結果取決於它的作用域。如果作用域鏈上沒有導致衝突的變數存在,使用它則是安全的。但在多人合作的項目中,這並不能保證,所以要慎用with。
2. 慎用eval
數組與對象
在JavaScript中,數組其實也是獨享,但是兩者在使用時有些細節需要註意。
1.字面量格式
創建對象或者數組時,註意在結尾用逗號分隔。如果分行,一行只能一個元素,示例代碼如下:
1 var foo = ['hello', 'world']; 2 var bar = { 3 hello: 'world', 4 pretty: 'code' 5 };
錯誤示例如下所示:
1 var foo = ['hello', 2 'world']; 3 var bar = { 4 hello: 'world', pretty: 'code' 5 };
2.for in 迴圈
使用for in迴圈時,請對對象使用,不要對數組使用,示例代碼如下:
1 var foo = []; 2 foo[100] = 100; 3 for (var i in foo) { 4 console.log(i); 5 } 6 for (var i = 0; i < foo.length; i++) { 7 console.log(i); 8 }
在上述代碼中,第一個迴圈只列印一次,而第二個迴圈則列印0~100,這並不滿足預期的值。
3.不要把數組當做對象使用
儘管在JavaScript內部實現中可以把數組當做對象來使用,如下所示:
1 var foo = [1, 2, 3]; 2 foo['hello'] = 'world'; 3 這在for in迭代時,會得到所有值 4 for (var i in foo) { 5 console.log(foo[i]); 6 } 7 也許你只是想得到hellow而已。
非同步
在Node中,非同步使用非常廣泛並且在實踐過程中形成了一些約定,這是以往不曾在意的點。
1.非同步回調函數的第一個參數應該是錯誤指示
並不是所有的回調函數都需要將第一個參數設計為錯誤對象,但是一旦涉及非同步,將會導致try catch無法捕獲到非同步回調期的異常。將第一個參數設計為錯誤對象,告知調用方是一個不錯的約定。示例代碼如下。
1 function(err, data){ 2 };
這個約定被很多流程式控制制庫所採用。遵循這個約定,可以享受社區流程式控制制庫帶來的業務編寫遍歷。
2.執行傳入的回調函數
在非同步方法中一旦有回調函數傳入,就一定要執行它,且不能多次執行。如果不執行,可能造成調用一直等待不結束,多次執行也可能會造成未預期的結果。
類與模塊
關於如何在JavaScript中實現繼承,有各種各樣的方式,但在Node中我們只推薦一種,那就是類繼承的方式。另外,在Node中,如果要將一個類作為一個模塊,就需要在意它的導出方式。
1.類繼承
一般情況下,我們採用Node推薦的類繼承方式,示例代碼如下:
1 function Socket(options) { 2 // ... 3 stream.Stream.call(this); 4 // ... 5 } 6 util.inherits(Socket, stream.Stream);
-
導出
所有供外部調用的方法或變數均需掛載在exports變數上。當需要將文件做一個類導出時,需要通過如下的方式掛載:
1 module.exprots = Class;
而不是通過
1 exports = Class;
私有方法無需因為測試等原因導出給外部,所以無需掛載。
註釋詳解
一般情況下,我們會對每個方法編寫註釋,這裡採用dox的推薦註釋,示例如下:
1 /** 2 * Queries some records 3 * Examples: 4 * ``` 5 * query('SELECT * FROM table', function (err, data) { 6 * // some code 7 * }); 8 * ``` 9 * @param {String} sql Queries 10 * @param {Function} callback Callback 11 */ 12 exports.query = function (sql, callback) { 13 // ... 14 };
dox的註釋規範來自與JSDoc。可以通過註釋生成對應的API文檔。
本文摘抄自 樸靈的深入淺出Node.js一書,感覺還不錯,在此分享。