javascript 代碼規範

目錄

1.爲什要遵照代碼規範

軟件bug的修復是昂貴的,而且隨着時間的推移,這些bug的成本也會增長,尤爲當這些bug潛伏並慢慢出如今已經發布的軟件中時。當你發現bug 的時候就當即修復它是最好的,此時你代碼要解決的問題在你腦中仍是很清晰的。不然,你轉移到其餘任務,忘了那個特定的代碼,一段時間後再去查看這些代碼就 須要:javascript

  • 花時間學習和理解這個問題
  • 花時間是瞭解應該解決的問題代碼
  • 還有問題,特別對於大的項目或是公司,修復bug的這位夥計不是寫代碼的那我的(且發現bug和修復bug的不是同一我的)。所以,必須下降理解代 碼花費的時間,不管是一段時間前你本身寫的代碼仍是團隊中的其餘成員寫的代碼。這關係到底線(營業收入)和開發人員的幸福,由於咱們更應該去開發新的激動 人心的事物而不是花幾小時幾天的時間去維護遺留代碼。

另外一個相關軟件開發生命的事實是,讀代碼花費的時間要比寫來得多。有時候,當你專一併深刻思考某個問題的時候,你能夠坐下來,一個下午寫大量的代碼。css

你的代碼很能很快就工做了,可是,隨着應用的成熟,還會有不少其餘的事情發生,這就要求你的進行進行審查,修改,和調整。例如:html

  • bug是暴露的
  • 新功能被添加到應用程序
  • 程序在新的環境下工做(例如,市場上出現新想瀏覽器)
  • 代碼改變用途
  • 代碼得徹底從頭從新,或移植到另外一個架構上或者甚至使用另外一種語言

因爲這些變化,不多人力數小時寫的代碼最終演變成花數週來閱讀這些代碼。這就是爲何建立可維護的代碼對應用程序的成功相當重要。java

可維護的代碼意味着:
  • 可讀的
  • 一致的
  • 可預測的
  • 看上去就像是同一我的寫的
  • 已記錄

2.編寫代碼需遵照的幾個原則

提示: 不遵照這些原則代碼也能運行起來。只是可能出現難以維護的現象。規範就像一種模式,你們按照一種模式來,那麼閱讀其餘人的代碼,成本就下降了。git

編寫代碼注意事項:

2.1. 儘可能減小聲明全局變量

2.2. 定義變量是,儘可能放到頂部

function func() {
    var a = 1,
        b = 2,
        sum = a + b,
        myobject = {},
        i,
        j;
    // function body...
}

注意:在es6中,使用let 定義,可能出現'暫時性死區', 具體想知道什麼叫作'暫時性死區' , 請查看阮一峯 ECMAScript 6 入門es6

2.3.for循環(for Loops)

// 次佳的循環
for (var i = 0; i < myarray.length; i++) {
// 使用myarray[i]作點什麼
}
//更好的方式
for (var i = 0, max = myarray.length; i < max; i++) {
// 使用myarray[i]作點什麼
}

**JSLint提示您這樣作,緣由是++和–-促進了「過度棘手(excessive trickiness)」。//zxx:這裏比較難翻譯,我想本意應該是讓代碼變得更加的棘手
若是你直接無視它,JSLint的plusplus選項會是false(默認是default)。**github

還有兩種變化的形式,其又有了些微改進,由於:正則表達式

  • 少了一個變量(無max)
  • 向下數到0,一般更快,由於和0作比較要比和數組長度或是其餘不是0的東西做比較更有效率

    //第一種變化的形式:
    var i, myarray = [];
    for (i = myarray.length; i–-;) {
    // 使用myarray[i]作點什麼
    }api

    //第二種使用while循環:數組

    var myarray = [],
    i = myarray.length;
    while (i–-) {
    // 使用myarray[i]作點什麼
    }

面兩種狀況優於前面兩種狀況。

2.4.for-in循環(for-in Loops)

for-in循環應該用在非數組對象的遍歷上,使用for-in進行循環也被稱爲「枚舉」。

從技術上將,你可使用for-in循環數組(由於JavaScript中數組也是對象),但這是不推薦的。由於若是數組對象已被自定義的功能加強,就可能發生邏輯錯誤。另外,在for-in中,屬性列表的順序(序列)是不能保證的。因此最好數組使用正常的for循環,對象使用for-in循環。

有個很重要的hasOwnProperty()方法,當遍歷對象屬性的時候能夠過濾掉從原型鏈上下來的屬性

// 對象
var man = {
    hands: 2,
    legs: 2,
    heads: 1
};

// 在代碼的某個地方
// 一個方法添加給了全部對象
if (typeof Object.prototype.clone === "undefined") {
    Object.prototype.clone = function () {};
}
====================================================================
// for-in 循環
for (var i in man) {
if (man.hasOwnProperty(i)) { // 過濾
    console.log(i, ":", man[i]);
}
}
/* 控制檯顯示結果
hands : 2
legs : 2
heads : 1
*/
==========================================================================
// 反面例子:
// for-in loop without checking hasOwnProperty()
for (var i in man) {
console.log(i, ":", man[i]);
}
/*
控制檯顯示結果
hands : 2
legs : 2
heads : 1
clone: function()
*/

2.5.(不)擴展內置原型((Not) Augmenting Built-in Prototypes)

增長內置的構造函數原型(如Object(), Array(), 或Function())挺誘人的,可是這嚴重下降了可維護性,由於它讓你的代碼變得難以預測。使用你代碼的其餘開發人員極可能更指望使用內置的 JavaScript方法來持續不斷地工做,而不是你另加的方法。

所以,不增長內置原型是最好的。你能夠指定一個規則,僅當下面的條件均知足時例外:

  • 能夠預期未來的ECMAScript版本或是JavaScript實現將一直將此功能看成內置方法來實現。例如,- 你能夠添加ECMAScript 5中描述的方法,一直到各個瀏覽器都迎頭遇上。這種狀況下,你只是提早定義了有用的方法。
  • 若是您檢查您的自定義屬性或方法已不存在——也許已經在代碼的其餘地方實現或已是你支持的瀏覽器JavaScript引擎部分。
  • 你清楚地文檔記錄並和團隊交流了變化。

    if (typeof Object.protoype.myMethod !== "function") {
           Object.protoype.myMethod = function () {
               // 實現...
           };
       }

通常狀況下,強烈不建議使用

2.6.避免隱式類型轉換(Avoiding Implied Typecasting )

JavaScript的變量在比較的時候會隱式類型轉換。這就是爲何一些諸如:false == 0 或 「」 == 0 返回的結果是true。爲避免引發混亂的隱含類型轉換,在你比較值和表達式類型的時候始終使用===和!==操做符。

var zero = 0;
if (zero === false) {
// 不執行,由於zero爲0, 而不是false
}

// 反面示例
if (zero == false) {
// 執行了...
}

2.7. 避免(Avoiding) eval()

若是你如今的代碼中使用了eval(),記住該咒語「eval()是魔鬼」。此方法接受任意的字符串,並看成JavaScript代碼來處理。當有 問題的代碼是事先知道的(不是運行時肯定的),沒有理由使用eval()。若是代碼是在運行時動態生成,有一個更好的方式不使用eval而達到一樣的目 標。例如,用方括號表示法來訪問動態屬性會更好更簡單:

// 反面示例
var property = "name";
alert(eval("obj." + property));

// 更好的
var property = "name";
alert(obj[property]);

3.編碼規範

3.1 縮進(Indentation)

代碼沒有縮進基本上就不能讀了。惟一糟糕的事情就是不一致的縮進,由於它看上去像是遵循了規範,可是可能一路上伴隨着混亂和驚奇。重要的是規範地使用縮進。

一些開發人員更喜歡用tab製表符縮進,由於任何人均可以調整他們的編輯器以本身喜歡的空格數來顯示Tab。有些人喜歡空格——一般四個,這都無所謂,只要團隊每一個人都遵循同一個規範就行了。這本書,例如,使用四個空格縮進,這也是JSLint中默認的縮進。

什麼應該縮進呢?規則很簡單——花括號裏面的東西。這就意味着函數體,循環 (do, while, for, for-in),if,switch,以及對象字面量中的對象屬性。下面的代碼就是使用縮進的示例:

function outer(a, b) {
    var c = 1,
        d = 2,
        inner;
    if (a > b) {
        inner = function () {
            return {
                r: c - d
            };
        };
    } else {
        inner = function () {
            return {
                r: c + d
            };
        };
    }
    return inner;
}

3.2 花括號{}(Curly Braces)

// 糟糕的實例
for (var i = 0; i < 10; i += 1)
alert(i);
// 好的實例
for (var i = 0; i < 10; i += 1) {
alert(i);
}

3.3 左花括號的位置(Opening Brace Location)

這個實例中,仁者見仁智者見智,但也有個案,括號位置不一樣會有不一樣的行爲表現。這是由於分號插入機制(semicolon insertion mechanism)——JavaScript是不挑剔的,當你選擇不使用分號結束一行代碼時JavaScript會本身幫你補上。這種行爲可能會致使麻 煩,如當你返回對象字面量,而左括號卻在下一行的時候

// 警告: 意外的返回值
function func() {
    return
    // 下面代碼不執行
    {
        name : "Batman"
    }
}

// 警告: 意外的返回值
function func() {
    return undefined;
    // 下面代碼不執行
    {
        name : "Batman"
    }
}

3.4 空格(White Space)

空格的使用一樣有助於改善代碼的可讀性和一致性。在寫英文句子的時候,在逗號和句號後面會使用間隔。在JavaScript中,你能夠按照一樣的邏輯在列表模樣表達式(至關於逗號)和結束語句(相對於完成了「想法」)後面添加間隔。

適合使用空格的地方包括:
  • for循環分號分開後的的部分:如for (var i = 0; i < 10; i += 1) {...}
  • for循環中初始化的多變量(i和max):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() {}
  • 匿名函數表達式function的後面: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;
}

最後須要注意的一個空格——花括號間距。最好使用空格:

  • 函數、if-else語句、循環、對象字面量的左花括號的前面({)
  • else或while之間的右花括號(})

    //{} 空格
    if (4) {
    console.log(1)
    } else if (3) {
    console.log(1)
    }
    var a = {}

4.命名規範

  • 另外一種方法讓你的代碼更具可預測性和可維護性是採用命名規範。這就意味着你須要用同一種形式給你的變量和函數命名。
  • 下面是建議的一些命名規範,你能夠原樣採用,也能夠根據本身的喜愛做調整。一樣,遵循規範要比規範是什麼更重要。

4.1以大寫字母寫構造函數(Capitalizing Constructors)

JavaScript並無類,但有new調用的構造函數:

var adam = new Person();

由於構造函數仍僅僅是函數,僅看函數名就能夠幫助告訴你這應該是一個構造函數仍是一個正常的函數。
命名構造函數時首字母大寫具備暗示做用,使用小寫命名的函數和方法不該該使用new調用:

function MyConstructor() {...}
function myFunction() {...}、

4.2 分隔單詞(Separating Words)

當你的變量或是函數名有多個單詞的時候,最好單詞的分離遵循統一的規範,有一個常見的作法被稱做「駝峯(Camel)命名法」,就是單詞小寫,每一個單詞的首字母大寫。

  • 對於構造函數,可使用大駝峯式命名法(upper camel case),如MyConstructor()。
  • 對於函數和方法名稱,你可使用小駝峯式命名法(lower camel case),像是myFunction(), calculateArea()和getFirstName()。

## 4.3 註釋(Writing Comments)

你必須註釋你的代碼,即便不會有其餘人向你同樣接觸它。一般,當你深刻研究一個問題,你會很清楚的知道這個代碼是幹嗎用的,可是,當你一週以後再回來看的時候,想必也要耗掉很多腦細胞去搞明白到底怎麼工做的。

很顯然,註釋不能走極端:每一個單獨變量或是單獨一行。可是,你一般應該記錄全部的函數,它們的參數和返回值,或是任何不尋常的技術和方法。要想到注 釋能夠給你代碼將來的閱讀者以諸多提示;閱讀者須要的是(不要讀太多的東西)僅註釋和函數屬性名來理解你的代碼。例如,當你有五六行程序執行特定的任務, 若是你提供了一行代碼目的以及爲何在這裏的描述的話,閱讀者就能夠直接跳過這段細節。沒有硬性規定註釋代碼比,代碼的某些部分(如正則表達式)可能註釋 要比代碼多。

5.css代碼規範

css規範咱們偉大的張旭鑫老師,講的很清楚。面向屬性的命名

這是比較好的命名規範。簡介來講,就是咱們先定義好一些經常使用基礎類樣式。組件則使用less,或者sass進行組裝,造成便可。

相關文章
相關標籤/搜索