前端javascript規範文檔

1、規範目的

爲提升團隊協做效率,便於前端後期優化維護,輸出高質量的文檔。javascript


2、基本準則

  • 符合web標準,結構表現行爲分離,兼容性優良。頁面性能方面,代碼要求簡潔明瞭有序, 儘量的減少服務器負載,保證最快的解析速度。
  • 項目的維護和二次開發多是直接或間接的團隊合做,因此建立易維護的代碼是一個項目成功與否的關鍵,易維護的代碼意味着具備以下特性:
    • 閱讀性好:如良好的註釋和命名規範,有文檔
    • 具備一致性:看起來如同一我的編寫
    • 代碼的鬆耦合,高度模塊化:將頁面內的元素視爲一個個模塊,相互獨立,儘可能避免耦合太高的代碼,從html,css,js三個層面都要考慮模塊化
    • 嚴格按照規範編寫代碼

3、命名規範

1. 目的

提升代碼可預測性和可維護性的方法是使用命名約定,這就意味着採用一致的方法來對變量和函數進行命名。css

2. 變量名

變量名包括全局變量,局部變量,類變量,函數參數html

3. 構造函數(類)命名

首字母大寫,駝峯式命名。前端

JS中沒有類,可是能夠用new調用構造函數:var man = new Person();java

4. 普通變量命名

首字母小寫,駝峯式命名,匈牙利命名web

如:nCheckCount 表示整形的數值ajax

5. 匈牙利命名法

匈牙利命名法語法:變量名=類型+對象描述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

6. 其餘前綴規範

可根據團隊及項目須要增長api

  • $:表示Jquery對象

    例如:$Content,$Module,一種比較普遍的Jquery對象變量命名規範。

  • fn:表示函數

    例如:fnGetName,fnSetAge;和上面函數的前綴略有不一樣,改用fn來代替,我的認爲fn可以更好的區分普通變量和函數變量。

7. 例外狀況

以根據項目及團隊須要,設計出針對項目須要的前綴規範,從而達到團隊開發協做便利的目的。

  • 做用域不大臨時變量能夠簡寫,好比:str,num,bol,obj,fun,arr。
  • 循環變量能夠簡寫,好比:i,j,k等。
  • 某些做爲不容許修改值的變量認爲是常量,所有字母都大寫。例如:COPYRIGHT,PI。常量能夠存在於函數中,也能夠存在於全局。必須採用全大寫的命名,且單詞以_分割,常量一般用於ajax請求url,和一些不會改變的數據。

8. 函數命名

普通函數:首字母小寫,駝峯式命名,統一使用動詞或者動詞+名詞形式

例如: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 彙集

9. 變量命名例子

  • 爲何須要這樣強制定義變量前綴?正式由於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對象的用戶,告訴他們這些方法在其餘地方不能確保必定可以正常工做,不能直接調用。

  • 總結:下面是一些使用下劃線約定的變量

    • 使用下劃線結尾來代表是私有變量,例如name_和getElements_()。
    • 使用一個下劃線前綴來表示受保護屬性,使用兩個下劃線前綴來表示私有屬性。

4、編寫註釋

爲代碼編寫註釋是很是重要的。一般人們在深刻思考一個問題時,會很是清楚這段代碼的工做原理。可是當過一週後再次回到該代碼時,可能會花上很長時間來回想起那段代碼究竟是幹什麼的。

  • 公共組件維護者和各欄目WD都須要在文件頭部加上註釋說明:

    /**
    *文件用途說明
    *做者姓名、聯繫方式(旺旺)
    *製做日期
    **/
  • 大的模塊註釋方法:

    //================
    // 代碼用途
    //================
  • 小的註釋;

    //代碼說明

    註釋單獨一行,不要在代碼後的同一行內加註釋。例如:

    //姓名
    var name = 「abc」;   V
    var name =」abc」; //姓名 X

5、使用空格

使用空格有助於改善代碼的可讀性和一致性。在撰寫英文文章時在逗號和區間範圍後面使用空格。在javascript採用一樣的邏輯,可在列表表達式(等價於逗號)和語句結束(等價於完成一次「思考」)後面添加空格。

用處一

  • 在分開for循環的各個部分的分號以後:例如,for (var i = 0; i < 10; i +=1){…}
  • 在for循環中初始化多個變量(i和最大值等):for (var i = 0, max = 10; i < max; i += 1){…}
  • 在限定數組項的逗號後面:var a = [1, 2, 3];
  • 對象屬性的逗號以後和將屬性名和屬性值分開的冒號以後:var o = {a: 1, b: 2};
  • 分隔開函數中各個參數的逗號以後:myFunc(a, b, c)
  • 在函數聲明的大括號以前:function myFunc() {}
  • 在匿名函數表達式以後:var myFunc = function () {};

用初二

空格的另一個很好的用途是用來分隔全部的操做符和操做,這也就是意味着在 +, -, *, =, <, >, <=, >=, ===, !==, &&, ||, += 等以後使用空格:

例子:

//大量空格,而且使用一致,是的代碼可讀性更好
//容許在閱讀的時候不用一口氣讀下去
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;
}

6、編寫API文檔

1. 生成API文檔的步驟:

  • 編寫特殊格式的代碼塊(即一些註釋塊)
  • 運行工具來解析代碼和註釋(工具如:JSDoc Toolkit和YUIDoc)
  • 發佈工具解析的結果,大多數狀況是採用HTML格式發佈(如網頁版的API文檔就是利用工具生成的)

簡單舉例

/**
* 翻轉一個字符串
*
* @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描述了對象的屬性。

2. 編寫API目的:

  • 爲API編寫註釋不只僅是一中提供參考文檔的簡便方法,並且還有其餘用途——經過再次審查代碼,提升代碼質量。
  • 在解決問題時寫出的解決方案僅僅是一個初稿。該解決方案能夠給出使人期待的輸出,可是該方案是不是最佳方案呢?改代碼是否可讀、易於理解、維護和升級呢?當您再次審視代碼時您將更加肯定代碼哪些部分能夠改進——如何使得代碼更容易繼續更新,移除一些不足之處等。它能夠極大地幫助您建立高質量的代碼。

7、推薦寫法

  1. 除了三目運算,if,else等禁止簡寫

    // 正確的書寫
     if (true) {
         alert(name);
     }
     console.log(name);
     // 不推薦的書寫
     if (true)
         alert(name);
     console.log(name);
     // 不推薦的書寫
     if (true)
     alert(name);
     console.log(name)
  2. 在須要以{}閉合的代碼段前增長換行,如: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];
                 }
             }
         }
     }
    換行能夠是空行,也能夠是註釋
  3. 使用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; //原則上,記得把這句話加上

    繼承從原則上來說,別改變他的構造函數,不然這個繼承就顯得很彆扭了~

  4. 使用局部變量緩存反覆查找的對象(包括但不限於全局變量、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等這些詞,都行,可是團隊開發的時候統一下比較好。

  5. 使用eval,採起$.parseJSON

    三個緣由:

    • 有注入風險,尤爲是ajax返回數據
    • 不方便debug
    • 效率低,eval是一個執行效率很低的函數

    建議: 使用new Function來代替eval的使用,最好就別用。


8、不規範寫法

  1. 句尾沒有分號

    var isHotel = json.type == "hotel" ? true : false

    這個是要引發注意的,好比:

    a = b        // 賦值
    (function(){
        //....
    })()         // 自執行函數

    未加分號,結果被解析成

    a = b(function(){//...})()  //將b()()返回的結果賦值給a
  2. 變量命名各類各樣

    var is_hotel;
    var isHotel;
    var ishotel;
  3. if 縮寫

    if (isHotel)
        console.log(true)
    else
        console.log(false)
  4. 使用 eval

    var json = eval(jsonText);
  5. 變量未定義處處都是

    function() {
        var isHotel = 'true';
        .......
    
        var html = isHotel ? '<p>hotel</p>' : "";
    }
  6. 超長函數

    function() {
        var isHotel = 'true';
        //....... 此處省略500行
        return false;
    }

9、須要注意的地方

  1. window.onload只能使用一次,使用屢次會被最後的覆蓋。

    解決方案:

    • 只引用一次window.onload
    • 使用jQuery的$(docuemnt.ready(function(){}); 可屢次使用
    • 使用函數封裝,代碼地址
  2. CSS放在頁頭引入,javascript放在頁尾引入

  3. 在上線以前,要編譯壓縮代碼
  4. 減小重排與重繪

10、擴展閱讀:

  1. JS技巧函數
  2. 瀏覽器的重排與重繪
  3. 進階書籍:《編寫高質量代碼-web前端開發修煉之道》

11、相關文檔

相關文章
相關標籤/搜索