代碼風格
命名
1. 為方法普舆、變量取一個好名字恬口, 使代碼易于理解
2. 文件中的私有屬性和方法名應(yīng)該以“__“開頭
3. 常量定義全部大寫校读, 并用下劃線分隔單詞
4. 方法的命名, 用動詞和動賓結(jié)構(gòu)祖能, 并采用首字母小寫的駝峰命名法歉秫。
說明:
get + 非布爾屬性名()
is + 布爾屬性名()
set + 屬性名()
has + 名詞/形容詞()
動詞()
動詞 + 賓語()
5. 為保證可讀性, 方法名不宜過長
6. 函數(shù)名养铸、屬性名遵循駝峰命名風格
7. 為全局屬性雁芙、函數(shù)使用命名空間
- js中只有函數(shù)有作用域,所以用函數(shù)模擬一個命名空間
function CartNamespace(){
function LoginBox(){/*登錄彈窗*/
this.show=function(){};
}
function ShopCartBusiness(){/*購物車業(yè)務(wù)*/
var _loginBox = undefined;
this.init=function(){
_loginBox = new LoginBox();
};
}
this.shopCart=new ShopCartBusiness();
}
var shopCart = new CartNamespace().shopCart;
shopCart.init();
8. 不要采用保留字作為鍵值或變量名揭厚, 如果確實需要却特, 請用保留字的同義詞
9. jQuery類型的變量以$開頭
注釋
- 盡量讓代碼來解釋自己
- 注釋應(yīng)解釋代碼的意圖, 而不是描述代碼怎么實現(xiàn)的
- 保證注釋與代碼一致筛圆, 避免產(chǎn)生誤導(dǎo)
- 注釋應(yīng)與其描述代碼位置相鄰裂明, 放在所注釋代碼的上方或右方, 并與代碼采用同樣的縮進
- 注釋和上面的代碼塊要有空行太援, 注釋的//和注釋內(nèi)容要有一個空格
- 不要用注釋保留廢棄的代碼
- 不要用注釋記錄修改日志
- 一般單行用
//
塊用/* */
文檔注釋用/** */
排版
1. 團隊應(yīng)使用一致的排版風格
2. 將排版風格固化到IDE的代碼格式化配置文件中闽晦, 并讓整個團隊使用
3. 在不同概念之間 提岔, 增加空行
4. 將邏輯緊密相關(guān)的代碼放在一起
5. 控制一行的寬度荠瘪, 不要超過120個字符
6. 在不同的概念間(關(guān)鍵字, 變量篮绰, 操作符)增加空格吠各, 以便清楚區(qū)分概念。
7. 統(tǒng)一采用4空格縮進
8. 數(shù)組和對象初始化纵散, 如果初始值不是很長翎承, 就保持寫在單行上瘩例。
9. 給if, for, do, while, switch等語句的執(zhí)行體加大括號{}
10. 控制文件的長度, 最好不要超過500行
11. 如果參數(shù)中有匿名函數(shù)聘惦, 函數(shù)體從調(diào)用該函數(shù)的左邊開始縮進4個空格, 而不是從function這個關(guān)鍵字開始, 這讓匿名函數(shù)更加易讀
12. 二元和三元操作符始終跟隨著前行剂跟, 如果一行實在放不下, 按上述的縮進風格進行換行
13. 字符串優(yōu)先使用單引號
14. 使用方法鏈時進行縮進衣洁, 同時使用前面加點, 強調(diào)這是方法調(diào)用而不是語句环凿, 如:
$(".item")
.find("tr")
.end()
.find(".open");
15. 花括號和語句在同一行。
16. 花括號前加一個空格
17. 在控制語句(if, while等)的括號前放一個空格考赛, 在函數(shù)調(diào)用及聲明中, 不在函數(shù)的參數(shù)列表前加空格忍抽。
方法
1. 方法設(shè)計的第一原則是要短小
2. 方法設(shè)計要遵循單一職責原則(SRP), 一個方法僅完成一個功能
3. 方法設(shè)計應(yīng)遵循單一抽象層次原則(SLAP)
SLAP原則祟绊, 是指一個方法中所有的操作處于相同的操作層, 否則阎姥, 跳躍的代碼的抽象層次破壞了代碼的流暢性御蒲。
4. 不要把方法的入?yún)斪龉ぷ髯兞?臨時變量府瞄, 除非特別需要
說明:
- 每個變量/參數(shù)都有自己獨特的功能, 讓一個變量承擔多個職責, 變量名無法清晰表達其功能换况, 會使程序無法理解舒裤。
- 如果參數(shù)是傳引用方式的, 則方法內(nèi)對參數(shù)的修改宏赘, 會傳遞到方法外闷游, 造成意外的錯誤扳埂, 如傳引用時梅尤, 不想方法內(nèi)修改入?yún)⒌模?建議在參數(shù)前加final關(guān)鍵字缰揪。
5. 方法的參數(shù)個數(shù)不宜過多
如果參數(shù)超過了7個, 則維護的難度很大, 建議減少參數(shù)個數(shù)僵驰。 如果多個參數(shù)同時多次出現(xiàn)在多個方法中, 說明這些參數(shù)緊密相關(guān), 可以將它們封裝到一個對象中。
語言特性
1. 定義類時漓摩, 盡量在原型下定義方法桌硫, 在構(gòu)造函數(shù)內(nèi)定義屬性, 從而最大程度發(fā)揮JavaScript引擎優(yōu)化機制
說明: 原型可以降低內(nèi)在占用边器, 提高運行效率。
2. 向數(shù)組添加元素時托修, 使用Array.push替代直接賦值
3. 有替代方案時忘巧, 禁用使用eval方法
說明:
- eval接受一個參數(shù)content, 如果content不是字符串睦刃, 則直接返回content, 否則執(zhí)行content語句砚嘴, 如果content語句執(zhí)行結(jié)果是一個值, 則返回此值工育, 否則,返回undefined, 這讓程序比較混亂艰赞, 導(dǎo)致可讀性差掷伙。
- 當eval()里面包含用戶輸入的話参袱, 存在安全風險, 可以用其它更佳整陌、更清晰、更安全的方式來寫代碼恩静。
4. 禁止使用with(){}
使用with讓你的代碼在語義上變得不清晰丐重, 因為with的對象可能與局部變量產(chǎn)生沖突, 從而改變你程序原本的用義。
5. 僅在對象構(gòu)造器、方法和閉包中使用this
- 在JavaScript里面, this指針代表的是執(zhí)行當前代碼對象的所有者筝闹, this語義很特別:
- 全局對象(大多數(shù)情況下)
- 調(diào)用者的作用域(使用eval時)
- DOM樹中的節(jié)點(添加事件處理函數(shù)時)
- 新創(chuàng)建的對象(在構(gòu)造器時)
- 其他對象(如果函數(shù)被call()或apply())
- 使用this時很容易出錯汞舱, 所有只有在下面兩種情況下使用:
- 在構(gòu)造器中
- 對象的方法(包括創(chuàng)建的閉包)中
6. 塊內(nèi)函數(shù)必須使用函數(shù)表達式聲明嘹履, 塊內(nèi)變量不能與函數(shù)內(nèi)的其他變量同名
7. 使用JSON.parse方法來分析JSON字符串
8. 每句代碼后必須加分號(;)
9. 使用JavaScript字面量而不是封裝基本類
10. 禁止修改內(nèi)置對象的原型
11. JavaScript與HTML分離
12. 聲明變量必須加var關(guān)鍵字
13. 在函數(shù)內(nèi)部使用”use strict"
說明:
- 消除JavaScript語法的一些不合理观腊、不嚴謹之處信轿, 減少一些怪異行為
- 消除代碼運行的一些不安全之處晃痴, 保證代碼運行的安全
- 提高編譯器效率残吩, 提高運行速度
- 為未來新版本的JavaScript做好鋪墊
在開啟“use strict"
后, 以下情況在運行腳本前會拋出SyntaError異常
- 八進制語法:
var n = 023
或var s = \047
- with語句
- 使用delete刪除一個變量名或函數(shù)(不是屬性名)
- 使用eval或arguments作為變量名或函數(shù)名
- 使用未來保留字
- 在語句塊使用函數(shù)聲明倘核, 如
if(a>b){function f(){}}
- 對象字面量中使用相同的屬性名
- 函數(shù)形參中使用多個相同的參數(shù)名
14. 訪問外部對象或外部對象屬性時泣侮, 必須先判斷是否為空
15. 判斷相等時, 使用===
和紧唱!==
16. 使用for/in循環(huán)必須結(jié)合實際具體應(yīng)用場景活尊, 正確使用hasOwnProperty方法
說明:
- for/in主要用于遍歷對象的屬性, 但不包括對象的內(nèi)置成員(如toString, valueOf)
- 如果重寫了Object的內(nèi)置屬性漏益, 使用for/in遍歷在不同瀏覽器上的結(jié)果是不同的
- 如果往原生對象上增加方法或?qū)傩裕?會被遍歷出來蛹锰, 如果不是業(yè)務(wù)需要遍歷property內(nèi)的屬性, 都要使用hasOwnProperty方法來提高代碼的健壯性
- 遍歷數(shù)組禁止使用for/in做遍歷绰疤, 請用普通的for循環(huán)來做遍歷铜犬。
17. 盡量避免給數(shù)組添加屬性
18. 推薦使用簡寫的條件表達式
19. 不要寫復(fù)雜的表達式
20. 采用括號明確計算的優(yōu)先級
21. 在switch語句的每一個case和default中都放置一條break語句。
22. var聲明會被提升至該作用域頂部, 所以聲明變量應(yīng)該寫在作用域頂部(因為即使var聲明不在頂部, 其實也會默認提升到作用域頂部, 所以顯式地寫在頂部可讀性更強).
性能編程規(guī)范
1. 緩存jQuery查詢結(jié)果
使用JavaScript訪問DOM元素是比較慢的, 所以使用選擇器的次數(shù)應(yīng)該越少越好, 并且盡可能緩存選中的結(jié)果, 便于后續(xù)反復(fù)使用
2. 避免使用所有元素選擇器$("*")
3. 優(yōu)先使用ID選擇器, 盡量給選擇器指定上下文context
jQuery選擇器性能最佳到最差如下:
- id選擇器
- 元素選擇器
- 類選擇器
- 屬性選擇器
- 偽類選擇器
4. 循環(huán)中減少DOM操作
5. 利用事件代理(冒泡)機制
每個JavaScript事件(如click)都會冒泡到父級節(jié)點, 當需要給多個元素調(diào)用同一個函數(shù)時, 這點很有用.
6. 盡量不要使用同步的ajax
同步的ajax請求會阻塞界面的渲染, 讓界面產(chǎn)生卡頓情況
內(nèi)存編程規(guī)范
1. 在滿足業(yè)務(wù)特性需求的情況下, 減少DOM對象的動態(tài)創(chuàng)建和刪除.
2. 禁止在循環(huán)轻庆、事件操作回調(diào)中使用文本+變量拼接的方式使用jQuery創(chuàng)建DOM癣猾。
說明:
jQuery在內(nèi)部實現(xiàn)中為了提高頻繁的DOM創(chuàng)建的性能, 會使用DocumentFragment緩存用戶創(chuàng)建的DOM余爆, 在重復(fù)創(chuàng)建的過程中使用緩存的DOM對象clone創(chuàng)建DOM纷宇, 從而提高DOM創(chuàng)建的效率。 但是蛾方, 這一優(yōu)化像捶, 僅適用于用戶頻繁創(chuàng)建的DOM內(nèi)容沒有變化的情況, 對于內(nèi)容不斷變化的話桩砰, 在頁面沒有卸載的情況下長時間運行
例如(不好)
$("#btn").on("click", function(e){
var ele = $("#hostelement");
var content = getValue();
var $span = $("<span>" + content + "</span>")
ele.append($span);
});
該方式下拓春, jQuery不會生成DocumentFragment對象, 也不會緩存DOM對象在其內(nèi)部的變量中五芝, 因此重復(fù)痘儡、頻繁使用時不會造成DOM泄露產(chǎn)生的問題內(nèi)存上漲辕万。
3. 盡量不要使用iframe
說明:
iframe適用于第三方集成枢步, 文件異步上傳等業(yè)務(wù), 非此類業(yè)務(wù)時渐尿, 建議使用HTML方式構(gòu)建醉途, 而不要使用iframe, iframe在加載性能和反復(fù)刪除情況下的內(nèi)存回收都不太理想砖茸, 尤其是低版本的瀏覽器隘擎。
事件監(jiān)聽
1. 正確使用DOM Event Level 2/3 標準進行事件的綁定和注銷。
2. 頁面卸載凉夯、動態(tài)刪除的DOM對象時要注銷綁定的事件監(jiān)聽货葬。
說明:
通常事件監(jiān)聽都是與DOM對象掛鉤的采幌, 當事件監(jiān)聽沒有被注銷時, 可能會造成JavaScript對象與DOM對象之間存在引用關(guān)系震桶, 尤其在大量使用閉包的情況下休傍, 容易造成JavaScript對象和DOM的循環(huán)引用。 在IE蹲姐、firefox上會造成內(nèi)存泄露磨取, 原因是由于IE和firefox都使用引用計數(shù)方式的垃圾回收算法。
var $btn = $(".btn");
$btn.off();
$btn.remove();
3. 不要在HTML標簽上嵌入JavaScript事件回調(diào)代碼
說明:
直接將JavaScript字符串作為DOM的事件處理邏輯柴墩, 容易引發(fā)IE8版本下無法釋放內(nèi)存的問題忙厌。
其它
1. 頁面局部刷新調(diào)整時, 要注銷相應(yīng)的定時器和延時器江咳。
說明:
定時器和延時器容易造成JavaScript對DOM的引用逢净, 在JavaScript對象本身沒有被釋放的情況下, 容易引起DOM對象的泄露歼指。
在局部頁面刷新時汹胃, 必須清理相應(yīng)的定時器, 否則會造成多個定時器同時執(zhí)行的業(yè)務(wù)問題和每個定時器對應(yīng)閉包所引用的內(nèi)存無法釋放的問題东臀。
2. 不要在JavaScript代碼中使用console.log輸出着饥。
說明:
console.log輸出會導(dǎo)致瀏覽器內(nèi)存上漲。 在IE下惰赋, 只要打開F12宰掉, console就會被激活, 后面即使關(guān)閉F12工具也無法關(guān)閉掉console赁濒, 內(nèi)存依然占用轨奄。
3. 使用完數(shù)組要將數(shù)組的長度置空
說明:
JavaScript是通過引用傳參, 需要在接口中或模塊中明確數(shù)組對象的生命周期責任拒炎, 否則可能會造成一處已經(jīng)置null, 而別處仍然持有引用挪拟, 導(dǎo)致內(nèi)存沒有釋放。