JavaScript編碼風格精選指南(編寫可維護的代碼規(guī)范)
如果你寫的代碼只是給自己看,不需要與多人共同協(xié)作;如果你寫的代碼不打算開源;如果你不進行code review;如果你不打算擔任前端工程師這一崗位,只是單純業(yè)余愛好;滿足以上任一條件,我建議你編碼不需要規(guī)范,怎么隨性怎么來,編碼規(guī)范束縛你的自由!
顯然,大多數(shù)人都不是以上的情況!那么javascript編碼規(guī)范就能解決以上的問題,還能夠增強代碼的簡潔性、可讀性、可擴展性。項目做到后期,每修改一次,所耗費的成本就越高,編碼規(guī)范能節(jié)省這樣的成本,并且能很好拓展升級原有系統(tǒng)功能。javascript編碼規(guī)范也是開源社區(qū)大家約定俗成的規(guī)則!
編碼規(guī)范前言
1、命名
“名副其實”——只做有意義的命名,規(guī)則如下:
可讀
可搜索
為相同類型的變量使用統(tǒng)一命名
在解構中命名
力求精簡,不添加不必要的上下文
屬性、變量名、類名使用名詞,函數(shù)名使用動詞
2、函數(shù)
短小
只做一件事
函數(shù)名使用動詞,要能夠說明它要做什么
函數(shù)的參數(shù)不應該超過三個
函數(shù)式編程優(yōu)于指令式編程
3、注釋
不要多余
注釋是對意圖的解釋
4、格式化
格式化是主觀的,但是團隊內應該保持一致
使用一致的大小寫
函數(shù)的調用方與被調用方應該靠近:從上到下閱讀代碼
借助 Format 工具
5、對象和數(shù)據結構
使用 getters 和 setters 能更好的處理對象及其數(shù)據結構
使用 set 可以讓驗證變得更容易
封裝內部實現(xiàn)
繼承這個類, 你可以重寫默認功能
使用 getting 和 setting 時, 容易添加日志和錯誤處理
6、單元測試
測試比發(fā)布更加重要。如果你沒有測試或者測試不夠充分,每次發(fā)布時你就不能確認沒有破壞任何事情。
測試必須具備:可讀性。
測試遵循 F(ast).I(ndependent).R(epeatable).S(elf-Validating).T(imely)。
1 縮進
每一行的層級由4個空格組成,避免使用制表符縮進。
2 行的長度
每行長度不超過80個字符,如果超過,應當在一個運算符(逗號,加號等)后換行。下一行應當增加兩級縮進(8個空格)。
//好的寫法 doSomething(arguments1, arguments2, arguments3, arguments4, arguments5)
3 運算符的行間距
二元運算符前后必須使用一個空格來保持表達式的整潔。操作符包括賦值運算符和邏輯運算符。
var found = (values[0] === item); if(found && (count > 10)); for(var i = 0; i < count; i++)
4 括號間距
當使用括號時,緊接左括號之后和緊接右括號之前不應該有空格。
5 對象直接量
對象直接量應當使用如下格式:
起始左花括號應當同表達式保持一行每個屬性的名值對應當保持一個縮進,第一個屬性應當在左花括號后另起一行每個屬性的名值對應當使用不含引號的屬性名,其后緊跟一個冒號(之前不含空格),而后是值倘若屬性值是函數(shù)類型,函數(shù)體應當在屬性名之下另起一行,而且其前后就均保留一個空格一組相關的屬性前后可以插入空行以提升代碼的可讀性結束的右花括號應當獨占一行
var obj = { key1: value1, key2: value2, func: function() { }, key3: value3 };
當對象字面量作為函數(shù)參數(shù)時,如果值是變量,其實花括號應當同函數(shù)名在同一行,所有其實先前列出的規(guī)則同樣適用
//好的寫法 doSomething({ key1: value1, key2: value2 }) //不好的寫法 doSomething({key1: value1,key2: value2})
6 注釋
頻繁地使用注釋有助于他人理解你的代碼,如下情況應當使用注釋:
代碼晦澀難懂可能被誤認為錯誤的代碼必要但并不明顯的針對特定瀏覽器的代碼對于對象、方法或者屬性,生成文檔是有必要的(使用恰當?shù)奈臋n注釋)
6.1 單行注釋
單行注釋應當用來說明一行或者一組相關的代碼。單行注釋可能有如下三種使用方式:
獨占一行的注釋,用來解釋下一行代碼在代碼行的尾部注釋,用來解釋它之前的代碼多行,用來注釋掉一個代碼塊
//好的寫法 if(condition){ //如果代碼執(zhí)行到這里,則表明通過了所有的安全檢查 allowed() } //不好的寫法:注釋前沒有空行 if(condition){ //如果代碼執(zhí)行到這里,則表明通過了所有的安全檢查 allowed() } //不好的寫法:錯誤的縮進 if(condition){ //如果代碼執(zhí)行到這里,則表明通過了所有的安全檢查 allowed() }
對于行尾的情況,代碼和注釋間至少一個空格
//好的寫法 var a = 10; // 這里是注釋 //不好的寫法 var a = 10;// 這里是注釋
6.2 多行注釋
多行注釋應當在代碼需要更多的文字去解釋的時候使用。每個多行注釋應當有如下三行
首行僅僅包含/*注釋開始,該行不能有其他文件接下來的行*開頭并保持左對齊。這些行可以有文字描述最后一行以*/結束并與先前行對齊。也不應再有其他文字
多行注釋應當保持同它描述的代碼一樣的縮進,后續(xù)每個*后加一個空格
//好的寫法 if (condition) { /* * 這里是說明 * 這也是 * 打字真他媽累 * 不好好看,我掐死你們 */ allowed(); }
7 變量聲明
所有變量在使用前都應當事先定義,使用一個var。
//好的寫法 var a = 1, b = 2, c = 3, d = 4; //不好的寫法 var a = 1; var b = 2; var c = 3; var d = 4; //不好的寫法 var a = 1, b = 2, c = 3, d = 4;
未初始化值得變量在后面
//好的寫法 var a = 1, b, c; // 不好的寫法 var b, c, a = 1;
8 函數(shù)聲明
函數(shù)應當在使用前提前定義,不是作為對象的方法的函數(shù),應當使用函數(shù)聲明的格式(function聲明)
// 好的寫法 function fn(arg1, arg2) { } // 不好的寫法:不恰當?shù)目崭? function fn (arg1, arg2){ } // 不好的寫法:花括號位置不對 function fn(arg1, arg2) { }
函數(shù)內的函數(shù)聲明,應當在var聲明后,立即定義。
//好的寫法 function outer() { var count = 10, name = 'fengyu', age = 18, empty; function inner() { } }
匿名函數(shù)的自執(zhí)行
// 推薦使用 (function (){}()); // 其他的都不推薦。
9 命名
變量和函數(shù)命名時要小心。命名應僅限于數(shù)字字母字符。某些情況可以使用下劃線。最好不好用美元符號(‘$’)和反斜杠(‘’)
變量命名采用駝峰式,首字母小寫,每個單詞首字母大寫,變量名的第一個單詞應當是一個名詞(而非動詞)以避免和函數(shù)混淆,不要再變量名中使用下劃線。
// 好的寫法 var accountNumber = "1234567"; // 不好的寫法:大寫字母開頭 var AccountNumber = "1234567"; // 不好的寫法:動詞開頭 var getAccountNumber = "1234567"; //不好的寫法:使用下劃線 var account_Number = "1234567";
函數(shù)名也使用駝峰,第一個單詞應當是動詞(而非名詞),也不要使用下劃線
// 好的寫法 function doSomething() { } // 不好的寫法:首字母大寫 function DoSomething() { } // 不好的寫法:名詞 function car() { } // 不好的寫法:下劃線 function do_something() { }
構造函數(shù)才能首字母大寫,名稱應當非動詞開頭
// 好的寫法 function MyObject() { } // 不好的寫法:首字母小寫 function myObject() { } // 不好的寫法:動詞開頭 function getMyObject() { }
常量(值不會被改變的變量)命名應當是全部大寫,不同單詞用下劃線隔開
// 好的寫法 var TOTAL_COUNT = 10; // 其他都是不好的寫法
對象的屬性同變量的命名規(guī)則相同。對象的方法同函數(shù)的命名規(guī)則相同,如果屬性或者方法是私有(不希望別人訪問),應當在之前加一個下劃線
// 好的寫法 var object = { _count: 10, _getCount: function (){ return this._count; } }
10 嚴格模式
嚴格模式應當僅限在函數(shù)內部使用,千萬不要在全局使用。
// 不好的寫法:全局使用嚴格模式 "use strict"; function doSomething() { //code }; // 好的寫法 function doSomething() { "use strict"; //code };
如果你期望在多個函數(shù)里使用嚴格模式而不需要多次聲明“use strict”,可以使用立即執(zhí)行的函數(shù)。
(function (){ "use strict"; function doSomething() { }; function doSomethingElse() { }; }());
11 賦值
當給變量賦值時,如果右側時含有比較語句的表達式,需要使用圓括號包裹。
// 好的寫法 var flag = (i < count); //不好的寫法 var flag = i < count;
12 等號運算符
使用===(嚴格等于)和!==(嚴格不相等)代替==(相等)和!=(不等)來避免弱類型轉換錯誤。
// 好的寫法 var same = (a === b); //不好的寫法 var same = (a == b);
13 三元運算符
三元運算符應當僅僅用在條件賦值語句中,而不要作為if的替代品。
// 好的寫法 var value = condition ? value1 : valule2; // 不好的寫法 condition ? doSomething() : doSomethingElse();
14 語句
14.1 簡單語句
每行最多只包含一條語句。所有簡單的語句都應該以分號結束
// 好的寫法 count++; a = b; // 不好的寫法 count++; a = b;
14.2 返回語句
返回語句當返回一個值得時候不應當使用圓括號包裹,除非在某些情況下這么做可以讓返回值更容易理解,例如:
return; return fengyu.length(); return (length > 18 ? length : 18);
14.3 復合語句
復合語句時大括號括起來得語句列表。
括起來得語句應當較符合語句多縮進一個層級開始得大括號應當在符合語句所在行的末尾;結束的大括號應當獨占一行且同復合語句的開始保持一樣的縮進當語句是控制結構的一部分時,諸如if或者for語句,所有的語句都需要用大括號括起來,也包括單個語句。這個約定是的我們更加方便地添加語句而不用擔心忘記加括號而引起bug。像if一樣的語句的開始的關鍵詞,其后應該緊跟一個空格,起始大括號應當在空格之后 ??14.3.1 if語句
if語句應當是下面的格式
if (condition) { statements } if (condition) { statements1 } else { statements2 } if (condition1) { statements1 } else if (condition2) { statements2 } else { statements3 }
絕不允許在if中省略花括號
// 好的寫法 if (condition) { doSomething(); } //不好的寫法:不恰當?shù)目崭? if(condition){ doSomething(); } // 不好的寫法:省略花括號 if(condition) doSomething(); // 不好的寫法:代碼在一行 if (condition) {doSomething();} // 不好的寫法:在一行還省略花括號 if (condition) doSomething();
??14.3.2 for語句
for類型的語句應當是下面的格式
for (initialization; condition; Step) { statements } for (variable in object) { statements }
for語句的初始化部分不應當有變量聲明
// 好的寫法 var i, len; for (i = 0, len = 10; i < len; i++) { //code } // 不好的寫法 for (var i = 0, len = 10; i < len; i++) { //code } for (var prop in object) { //code }
14.3.3 while語句
while類的語句應當是下面格式
while (condition) { //code }
14.3.4 do…while語句
do類語句應當是下面格式
do { //code } while (condition);
14.3.5 switch語句
格式如下:
#除了第一個case之外,包括default在內的每一個case之前都應當有一個空行 switch (expression) { case exp1: //code break; case exp2: //code break; default: //code break; }
如果一個switch不包含default的情況,應當用注釋代替
switch (expression) { case exp1: //code break; case exp2: //code break; // 沒有default }
15 留白
在邏輯相關的代碼塊之間添加空行可以提高代碼的可讀性。
兩行空行僅限在如下情況中使用
在不同的源代碼文件之間在類和接口定義之間
單行空行僅限在如下情況中使用
方法之間
方法中局部變量和第一行語句中間
多行或者單行注釋之前
方法中邏輯代碼塊之間以提升代碼的可讀性
空格應當在如下情況中使用
關鍵詞后跟括號的情況應當用空格隔開
參數(shù)列表中逗號之后應當留一個空格
所有的除了點(.)之外的二元運算符,其操作數(shù)都應當用空格隔開。單目運算符的操作數(shù)事件不應該用空白隔開,諸如一元減號,遞增(++),遞減(–)
for語句中的表達式之間應當用空格隔開
16 需要避免的
切勿使用像String一類的原始包裝類型創(chuàng)建新的對象。
避免使用eval()
避免使用with語句(其實該語句已經被廢除了)
17 關于命名
? 變量:必須采用小駝峰式命名法。
命名規(guī)范:前綴應當是名詞。(函數(shù)的名字前綴為動詞,以此區(qū)分變量和函數(shù))
命名建議:盡量在變量名字中體現(xiàn)所屬類型,如:length、count等表示數(shù)字類型;而包含name、title表示為字符串類型。
// 好的命名方式 let maxCount = 10; let tableTitle = 'LoginTable'; // 不好的命名方式 let setCount = 10; let getTitle = 'LoginTable';
常量:必須采用全大寫的命名,且單詞以_分割,常量通常用于ajax請求url,和一些不會改變的數(shù)據
命名規(guī)范:使用大寫字母和下劃線來組合命名,下劃線用以分割單詞。
const MAX_COUNT = 10; const URL = 'http://.com';
函數(shù)
- 命名方法:小駝峰式命名法。
- 命名規(guī)范:前綴應當為動詞。
- 命名建議:可使用常見動詞約定
動詞 | 含義 | 返回值 |
---|---|---|
can | 判斷是否可執(zhí)行某個動作(權限) | 函數(shù)返回一個布爾值。true:可執(zhí)行;false:不可執(zhí)行 |
has | 判斷是否含有某個值 | 函數(shù)返回一個布爾值。true:含有此值;false:不含有此值 |
is | 判斷是否為某個值 | 函數(shù)返回一個布爾值。true:為某個值;false:不為某個值 |
get | 獲取某個值 | 函數(shù)返回一個非布爾值 |
set | 設置某個值 | 無返回值、返回是否設置成功或者返回鏈式對象 |
load | 加載某些數(shù)據 | 無返回值或者返回是否加載完成的結果 |
// 是否可閱讀 function canRead(): boolean { return true; } // 獲取名稱 function getName(): string { return this.name; }
類 & 構造函數(shù)
命名方法:大駝峰式命名法,首字母大寫。
命名規(guī)范:前綴為名稱。
示例:
class Person { public name: string; constructor(name) { this.name = name; } } const person = new Person('mevyn');
類的成員
類的成員包含:
公共屬性和方法:跟變量和函數(shù)的命名一樣。私有屬性和方法:前綴為_(下劃線),后面跟公共屬性和方法一樣的命名方式。
示例:
class Person { private _name: string; constructor() { } // 公共方法 getName() { return this._name; } // 公共方法 setName(name) { this._name = name; } } const person = new Person(); person.setName('mervyn'); person.getName(); // ->mervyn
18 注釋規(guī)范
js 支持三種不同類型的注釋:行內注釋、單行注釋和多行注釋:
行內注釋 說明:行內注釋以兩個斜線開始,以行尾結束。語法:code // 這是行內注釋使用方式://(雙斜線)與代碼之間保留一個空格,并且//(雙斜線)與注釋文字之間保留一個空格。
命名建議:
// 用來顯示一個解釋的評論
// -> 用來顯示表達式的結果,
// >用來顯示 console 的輸出結果,
示例:
function test() { // 測試函數(shù) console.log('Hello World!'); // >Hello World! return 3 + 2; // ->5 }
單行注釋 說明:單行注釋以兩個斜線開始,以行尾結束。語法:// 這是單行注釋使用方式:單獨一行://(雙斜線)與注釋文字之間保留一個空格。
示例:
// 調用了一個函數(shù);1)單獨在一行 setTitle();
多行注釋 說明:以 /* 開頭, */ 結尾語法:/* 注釋說明 */使用方法:若開始/和結束/都在一行,推薦采用單行注釋。若至少三行注釋時,第一行為/,最后行為/,其他行以開始,并且注釋文字與保留一個空格。
示例:
/* * 代碼執(zhí)行到這里后會調用setTitle()函數(shù) * setTitle():設置title的值 */ setTitle();
函數(shù)(方法)注釋 說明:函數(shù)(方法)注釋也是多行注釋的一種,但是包含了特殊的注釋要求,參照JSDoc語法:
/** * 函數(shù)說明 * @關鍵字 */
常用注釋關鍵字:(只列出一部分,并不是全部)
注釋名 | 語法 | 含義 | 示例 |
---|---|---|---|
@param | @param 參數(shù)名 {參數(shù)類型} 描述信息 | 描述參數(shù)的信息 | @param name {String} 傳入名稱 |
@return | @return {返回類型} 描述信息 | 描述返回值的信息 | @return {Boolean} true:可執(zhí)行;false:不可執(zhí)行 |
@author | @author 作者信息 [附屬信息:如郵箱、日期] | 描述此函數(shù)作者的信息 | @author 張三 2015/07/21 |
@version | @version XX.XX.XX | 描述此函數(shù)的版本號 | @version 1.0.3 |
@example | @example 示例代碼 | 演示函數(shù)的使用 | @example setTitle(‘測試’) |
/** * 合并Grid的行 * @param grid {Ext.Grid.Panel} 需要合并的Grid * @param cols {Array} 需要合并列的Index(序號)數(shù)組;從0開始計數(shù),序號也包含。 * @param isAllSome {Boolean} :是否2個tr的cols必須完成一樣才能進行合并。true:完成一樣;false(默認):不完全一樣 * @return void * @author polk6 2015/07/21 * @example * _________________ _________________ * | 年齡 | 姓名 | | 年齡 | 姓名 | * ----------------- mergeCells(grid,[0]) ----------------- * | 18 | 張三 | => | | 張三 | * ----------------- - 18 --------- * | 18 | 王五 | | | 王五 | * ----------------- ----------------- */ function mergeCells(grid: Ext.Grid.Panel, cols: Number[], isAllSome: boolean = false) { // Do Something }
不要保存 this 的引用。使用 Function#bind。
// bad function () { var self = this; return function () { console.log(self); }; } // bad function () { var that = this; return function () { console.log(that); }; } // bad function () { var _this = this; return function () { console.log(_this); }; } // good function () { return function () { console.log(this); }.bind(this); }
給函數(shù)命名。這在做堆棧軌跡時很有幫助。
// bad var log = function (msg) { console.log(msg); }; // good var log = function log(msg) { console.log(msg); };
如果你的文件導出一個類,你的文件名應該與類名完全相同。
// file contents class CheckBox { // ... } module.exports = CheckBox; // in some other file // bad var CheckBox = require('./checkBox'); // bad var CheckBox = require('./check_box'); // good var CheckBox = require('./CheckBox');
19 模塊
模塊應該以 ! 開始。這樣確保了當一個不好的模塊忘記包含最后的分號時,在合并代碼到生產環(huán)境后不會產生錯誤。
詳細說明
文件應該以駝峰式命名,并放在同名的文件夾里,且與導出的名字一致。
增加一個名為 noConflict() 的方法來設置導出的模塊為前一個版本并返回它。
永遠在模塊頂部聲明 ‘use strict’;。
// fancyInput/fancyInput.js !function (global) { 'use strict'; var previousFancyInput = global.FancyInput; function FancyInput(options) { this.options = options || {}; } FancyInput.noConflict = function noConflict() { global.FancyInput = previousFancyInput; return FancyInput; }; global.FancyInput = FancyInput; }(this);
20 構造函數(shù)
給對象原型分配方法,而不是使用一個新對象覆蓋原型。覆蓋原型將導致繼承出現(xiàn)問題:重設原型將覆蓋原有原型!
function Jedi() { console.log('new jedi'); } // bad Jedi.prototype = { fight: function fight() { console.log('fighting'); }, block: function block() { console.log('blocking'); } }; // good Jedi.prototype.fight = function fight() { console.log('fighting'); }; Jedi.prototype.block = function block() { console.log('blocking'); };
方法可以返回 this 來實現(xiàn)方法鏈式使用。
// bad Jedi.prototype.jump = function jump() { this.jumping = true; return true; }; Jedi.prototype.setHeight = function setHeight(height) { this.height = height; }; var luke = new Jedi(); luke.jump(); // => true luke.setHeight(20); // => undefined // good Jedi.prototype.jump = function jump() { this.jumping = true; return this; }; Jedi.prototype.setHeight = function setHeight(height) { this.height = height; return this; }; var luke = new Jedi(); luke.jump() .setHeight(20);
21 小tips
代碼風格有很多種,就拿縮進來說:
jQuery核心風格指南明確規(guī)定使用制表符縮進
Dauglas Crockford的JavaScript代碼規(guī)范規(guī)定使用4個空格字符縮進
SproutCore風格指南規(guī)定使用2個空格縮進
Google的Javascript風格指南規(guī)定使用2個空格縮進
Dojo編程風格指南規(guī)定使用制表符縮進
因此,風格很多,大致了解一下,以所在的團隊風格為準。
總結
到此這篇關于JavaScript編碼風格指南(編寫可維護的代碼規(guī)范)的文章就介紹到這了,更多相關JavaScript編碼規(guī)范內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Some tips of wmi scripting in jscript (1)
Some tips of wmi scripting in jscript (1)...2007-04-04