爲提升團隊協做效率,便於前端後期優化維護,輸出高質量的文檔。javascript
提升代碼可預測性和可維護性的方法是使用命名約定,這就意味着採用一致的方法來對變量和函數進行命名。css
變量名包括全局變量,局部變量,類變量,函數參數html
首字母大寫,駝峯式命名。前端
JS中沒有類,可是能夠用new調用構造函數:var man = new Person();java
首字母小寫,駝峯式命名,匈牙利命名web
如:nCheckCount 表示整形的數值ajax
匈牙利命名法語法:變量名=類型+對象描述json
提示: 雖然JavaScript變量表面上沒有類型,可是JavaScript內部仍是會爲變量賦予相應的類型小程序
JavaScript變量起名類型 | 變量命名前綴 | 舉例 |
---|---|---|
Array 數組 | a | aList,aGroup |
Boolean 邏輯 | b | bChecked,bHasLogin |
Function 函數 | f | fGetHtml,fInit |
Integer 數字 | n | nPage,nTotal |
Object 對象 | o | oButton,oDate |
Regular Expression 正則 | r | rDomain,rEmail |
String 字符 | s | sName,sHtml |
可根據團隊及項目須要增長api
$:表示Jquery對象
例如:$Content,$Module,一種比較普遍的Jquery對象變量命名規範。
fn:表示函數
例如:fnGetName,fnSetAge;和上面函數的前綴略有不一樣,改用fn來代替,我的認爲fn可以更好的區分普通變量和函數變量。
以根據項目及團隊須要,設計出針對項目須要的前綴規範,從而達到團隊開發協做便利的目的。
普通函數:首字母小寫,駝峯式命名,統一使用動詞或者動詞+名詞形式
例如:fnGetVersion(),fnSubmitForm(),fnInit();涉及返回邏輯值的函數可使用is,has,contains等表示邏輯的詞語代替動詞,例如:fnIsObject(),fnHasClass(),fnContainsElment()。
內部函數:使用_fn+動詞+名詞形式,內部函數必需在函數最後定義。
例如:
function fnGetNumber(nTotal) { if (nTotal < 100) { nTotal = 100; } return _fnAdd(nTotal); function _fnAdd(nNumber) { nNumber++; return nNumber; } } alert(fGetNumber(10)); //alert 101
對象方法與事件響應函數:對象方法命名使用fn+對象類名+動詞+名詞形式;
例如: fnAddressGetEmail(),
事件響應函數:fn+觸發事件對象名+事件名或者模塊名
例如:fnDivClick(),fnAddressSubmitButtonClick()
函數方法經常使用的動詞:
get 獲取/set 設置, add 增長/remove 刪除 create 建立/destory 移除 start 啓動/stop 中止 open 打開/close 關閉, read 讀取/write 寫入 load 載入/save 保存, create 建立/destroy 銷燬 begin 開始/end 結束, backup 備份/restore 恢復 import 導入/export 導出, split 分割/merge 合併 inject 注入/extract 提取, attach 附着/detach 脫離 bind 綁定/separate 分離, view 查看/browse 瀏覽 edit 編輯/modify 修改, select 選取/mark 標記 copy 複製/paste 粘貼, undo 撤銷/redo 重作 insert 插入/delete 移除, add 加入/append 添加 clean 清理/clear 清除, index 索引/sort 排序 find 查找/search 搜索, increase 增長/decrease 減小 play 播放/pause 暫停, launch 啓動/run 運行 compile 編譯/execute 執行, debug 調試/trace 跟蹤 observe 觀察/listen 監聽, build 構建/publish 發佈 input 輸入/output 輸出, encode 編碼/decode 解碼 encrypt 加密/decrypt 解密, compress 壓縮/decompress 解壓縮 pack 打包/unpack 解包, parse 解析/emit 生成 connect 鏈接/disconnect 斷開, send 發送/receive 接收 download 下載/upload 上傳, refresh 刷新/synchronize 同步 update 更新/revert 復原, lock 鎖定/unlock 解鎖 check out 簽出/check in 簽入, submit 提交/commit 交付 push 推/pull 拉, expand 展開/collapse 摺疊 begin 起始/end 結束, start 開始/finish 完成 enter 進入/exit 退出, abort 放棄/quit 離開 obsolete 廢棄/depreciate 廢舊, collect 收集/aggregate 彙集
爲何須要這樣強制定義變量前綴?正式由於javascript是弱語言形成的。在定義大量變量的時候,咱們須要很明確的知道當前變量是什麼屬性,若是隻經過普通單詞,是很難區分的。
普通代碼
var checked = false; var check = function() { return true; } /** some code **/ if(check) {//已經沒法很確切知道這裏是要用checked仍是check()從而致使邏輯錯誤 //do some thing }
規範後代碼
var bChecked = false; var fnCheck = function() { return true; } /** some code **/ if(bChecked) { // do some thing } if(fnCheck()) { // do other thing }
如何標明私有方法或私有屬性?
var person = { getName: function () { return this._getFirst() + ' ' + this._getLast(); }, _getFirst: function () { //... }, _getLast: function (){ //... } };
在這個例子中,getName()覺得這這是API的一個公開的方法,而_getFirst()和_getLast()意味着這是一個私有函數。儘管他們都是普通的公開方法,可是使用下劃線前綴的表示方法能夠提醒使用person對象的用戶,告訴他們這些方法在其餘地方不能確保必定可以正常工做,不能直接調用。
總結:下面是一些使用下劃線約定的變量
爲代碼編寫註釋是很是重要的。一般人們在深刻思考一個問題時,會很是清楚這段代碼的工做原理。可是當過一週後再次回到該代碼時,可能會花上很長時間來回想起那段代碼究竟是幹什麼的。
公共組件維護者和各欄目WD都須要在文件頭部加上註釋說明:
/** *文件用途說明 *做者姓名、聯繫方式(旺旺) *製做日期 **/
大的模塊註釋方法:
//================ // 代碼用途 //================
小的註釋;
//代碼說明
註釋單獨一行,不要在代碼後的同一行內加註釋。例如:
//姓名 var name = 「abc」; V var name =」abc」; //姓名 X
使用空格有助於改善代碼的可讀性和一致性。在撰寫英文文章時在逗號和區間範圍後面使用空格。在javascript採用一樣的邏輯,可在列表表達式(等價於逗號)和語句結束(等價於完成一次「思考」)後面添加空格。
用處一
用初二
空格的另一個很好的用途是用來分隔全部的操做符和操做,這也就是意味着在 +, -, *, =, <, >, <=, >=, ===, !==, &&, ||, += 等以後使用空格:
例子:
//大量空格,而且使用一致,是的代碼可讀性更好 //容許在閱讀的時候不用一口氣讀下去 var d = 0, a = b +1; if ( a && b && c) { d = a % c; a += d; } //反模式 //缺乏空格或空格使用不一致,使得代碼比較混亂 var d= 0; a =b+1; if (a&& b&& c) { d=a %c; a+= d; }
簡單舉例:
/** * 翻轉一個字符串 * * @param {String} 輸入須要翻轉的字符串 * @return {String} 翻轉後的字符串 **/ var reverse = function (input) { //... return output; };
YUIDoc範例:
完整範例:本程序由一個文件(app.js)組成,該文件僅有一個模塊(myapp)。
app.js:
/** * 個人javascript應用程序 * * @module myapp */ //使用命名空間來定義一個空對象 var MYAPP = {}; //定義一個包含兩個方法(sum()和multi())的math_stuff對象 /** * @namespace MYAPP * class math_stuff */ MYAPP.math_stuff = { /** * Sums two numbers * * @method sum * param {Number} 是第一個數 * param {Number} 是第二個數 * return {Number} 兩個輸入的總和 */ sum: function (a, b) { return a + b; }, /** * Multiplies two numbers * param {Number} 是第一個數 * param {Number} 是第二個數 * return {Number} 兩個輸入相乘後結果 */ multi: function (a, b) { return a * b; } };
@namespace:這裏用於命名包含以上對象的全局引用的名稱
@class:這裏有些命名不當,他實際意思是指對象或者構造函數
@method:定義對象中的方法和方法名
@param:列舉函數所使用的參數。其中將參數類型用大括號括起來,並在其後註釋參數名及描述。
@return:相似於@param,這裏用於描述返回值的,而且該方法沒有名稱。
@constructor:代表這個「類」其實是一個構造函數
@property和@type描述了對象的屬性。
除了三目運算,if,else等禁止簡寫
// 正確的書寫 if (true) { alert(name); } console.log(name); // 不推薦的書寫 if (true) alert(name); console.log(name); // 不推薦的書寫 if (true) alert(name); console.log(name)
在須要以{}閉合的代碼段前增長換行,如:for if
// 沒有換行,小的代碼段沒法區分 if (wl && wl.length) { for (i = 0, l = wl.length; i < l; ++i) { p = wl[i]; type = Y.Lang.type(r[p]); if (s.hasOwnProperty(p)) { if (merge && type == 'object') { Y.mix(r[p], s[p]); } else if (ov || !(p in r)) { r[p] = s[p]; } } } } // 有了換行,邏輯清楚多了 if (wl && wl.length) { for (i = 0, l = wl.length; i < l; ++i) { p = wl[i]; type = Y.Lang.type(r[p]); if (s.hasOwnProperty(p)) { // 處理merge邏輯 if (merge && type == 'object') { Y.mix(r[p], s[p]); } else if (ov || !(p in r)) { r[p] = s[p]; } } } } 換行能夠是空行,也能夠是註釋
使用Function進行類的定義,不推薦繼承,如需繼承採用成熟的類庫實現繼承
// 類的實現 function Person(name) { this.name = name; } Person.prototype.sayName = function() { alert(this.name); }; var me = new Person("Nicholas"); // 將this放到局部變量self function Persion(name, sex) { var self = this; self.name = name; self.sex = sex; }
平時我們寫代碼,基本都是小程序,真心用不上什麼繼承,並且繼承並非JS的擅長的語言特性,儘可能少用。若是非要使用的話,注意一點:
function A(){ //... } function B(){ //... } B.prototype = new A(); B.prototype.constructor = B; //原則上,記得把這句話加上
繼承從原則上來說,別改變他的構造函數,不然這個繼承就顯得很彆扭了~
使用局部變量緩存反覆查找的對象(包括但不限於全局變量、dom查詢結果、做用域鏈較深的對象)
// 緩存對象 var getComment = function() { var dom = $("#common-container"), // 緩存dom appendTo = $.appendTo, // 緩存全局變量 data = this.json.data; // 緩存做用域鏈較深的對象 } //當須要緩存this時必須使用self變量進行緩存 // 緩存this function Row(name) { var self = this; self.name = name; $(".row").click(function() { self.getName(); }); }
self是一個保留字,不過用它也不要緊。在這裏,看我的愛好吧,能夠用_this, that, me等這些詞,都行,可是團隊開發的時候統一下比較好。
使用eval,採起$.parseJSON
三個緣由:
建議: 使用new Function來代替eval的使用,最好就別用。
句尾沒有分號
var isHotel = json.type == "hotel" ? true : false
這個是要引發注意的,好比:
a = b // 賦值 (function(){ //.... })() // 自執行函數
未加分號,結果被解析成
a = b(function(){//...})() //將b()()返回的結果賦值給a
變量命名各類各樣
var is_hotel; var isHotel; var ishotel;
if 縮寫
if (isHotel) console.log(true) else console.log(false)
使用 eval
var json = eval(jsonText);
變量未定義處處都是
function() { var isHotel = 'true'; ....... var html = isHotel ? '<p>hotel</p>' : ""; }
超長函數
function() { var isHotel = 'true'; //....... 此處省略500行 return false; }
window.onload只能使用一次,使用屢次會被最後的覆蓋。
解決方案:
CSS放在頁頭引入,javascript放在頁尾引入