大前端團隊代碼規範

1 前言

隨着團隊人數的增長,每一個人的代碼編寫喜愛不一樣,代碼風格也迥然不一樣。若是有一個你們的統一的願意遵照的代碼規範,確定事半功倍,提升效率,避免代碼Review重構javascript

其中一部分規則參考了 騰訊alloyteam團隊的代碼規範,若有錯誤,請指出,將會很是感謝。css

堅持好的代碼風格規範,從你我作起。html

2 命名規範

1) 項目命名

所有采用小寫方式, 如下劃線分隔。vue

例:my_project_namehtml5

2 )目錄命名

參照項目命名規則;java

有複數結構時,要採用複數命名法。jquery

例:pages, assets, directives, components, mixins, utilsgit

3)javaScript 文件命名

參照項目命名規則。github

例:account_model.jsweb

4)CSS,less文件命名

參照項目命名規則。

例:retina_sprites.less

5)HTML文件命名

參照項目命名規則。

例:error_report.html

6) 若是使用Vue或者React技術棧,組件Component命名

全部組件名字須要首字母大寫,而後駝峯格式

例:CalendarList.vue

3 HTML

1) 語法

  • 縮進使用soft tab(4個空格);
  • 嵌套的節點應該縮進;
  • 在屬性上,使用雙引號,不要使用單引號;
  • 屬性名全小寫,用中劃線作分隔符;
  • 不要在自動閉合標籤結尾處使用斜線(HTML5 規範 指出他們是可選的);
  • 不要忽略可選的關閉標籤;
<!DOCTYPE html>
<html>
    <head>
        <title>Page title</title>
    </head>
    <body>
        <img src="images/company_logo.png" alt="Company" />

        <h1 class="hello-world">Hello, world!</h1>
    </body>
</html>
複製代碼

2) HTML5 doctype

在頁面開頭使用這個簡單地doctype來啓用標準模式,使其在每一個瀏覽器中儘量一致的展示;

雖然doctype不區分大小寫,可是按照慣例,doctype大寫 (關於html屬性,大寫仍是小寫)。

<!DOCTYPE html>
<html>
	...
</html>
複製代碼

3) lang屬性

根據HTML5規範:

應在html標籤上加上lang屬性。這會給語音工具和翻譯工具幫助,告訴它們應當怎麼去發音和翻譯。

更多關於 lang 屬性的說明在這裏

在sitepoint上能夠查到語言列表

但sitepoint只是給出了語言的大類,例如中文只給出了zh,可是沒有區分香港,臺灣,大陸。而微軟給出了一份更加詳細的語言列表,其中細分了zh-cn, zh-hk, zh-tw。

<!DOCTYPE html>
<html lang="en-us">
    ...
</html>
複製代碼

4) 字符編碼

經過聲明一個明確的字符編碼,讓瀏覽器輕鬆、快速的肯定適合網頁內容的渲染方式,一般指定爲'UTF-8'。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
    </head>
    ...
</html>
複製代碼

5) IE兼容模式

用 `` 標籤能夠指定頁面應該用什麼版本的IE來渲染;

若是你想要了解更多,請點擊這裏

不一樣doctype在不一樣瀏覽器下會觸發不一樣的渲染模式(這篇文章總結的很到位)。

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=Edge">
    </head>
    ...
</html>
複製代碼

6) 引入CSS, JS

根據HTML5規範, 一般在引入CSS和JS時不須要指明 type,由於 text/csstext/javascript 分別是他們的默認值。

HTML5 規範連接

<!-- External CSS -->
<link rel="stylesheet" href="code_guide.css">

<!-- In-document CSS -->
<style> ... </style>

<!-- External JS -->
<script src="code_guide.js"></script>

<!-- In-document JS -->
<script> ... </script>
複製代碼

7) 屬性順序

屬性應該按照特定的順序出現以保證易讀性;

  • class
  • id
  • name
  • data-*
  • src, for, type, href, value , max-length, max, min, pattern
  • placeholder, title, alt
  • aria-*, role
  • required, readonly, disabled

class是爲高可複用組件設計的,因此應處在第一位;

id 具體且應該儘可能少使用,因此將它放在第二位。

<a class="..." id="..." data-modal="toggle" href="#">Example link</a>

<input class="form-control" type="text">

<img src="..." alt="...">
複製代碼

8) boolean屬性

boolean屬性指不須要聲明取值的屬性,XHTML須要每一個屬性聲明取值,可是HTML5並不須要;

更多內容能夠參考 WhatWG section on boolean attributes

boolean屬性的存在表示取值爲true,不存在則表示取值爲false。

<input type="text" disabled>

<input type="checkbox" value="1" checked>

<select>
    <option value="1" selected>1</option>
</select>
複製代碼

9) JS生成標籤

在JS文件中生成標籤讓內容變得更難查找,更難編輯,性能更差。應該儘可能避免這種狀況的出現。

10) 減小標籤數量

在編寫HTML代碼時,須要儘可能避免多餘的父節點;

不少時候,須要經過迭代和重構來使HTML變得更少。

<!-- 不建議這麼作 -->
<span class="avatar">
    <img src="...">
</span>

<!-- 建議這麼作 -->
<img class="avatar" src="...">
複製代碼

11) 實用高於完美

儘可能遵循HTML標準和語義,可是不該該以浪費實用性做爲代價;

任什麼時候候都要用盡可能小的複雜度和儘可能少的標籤來解決問題。

4 css、less

1) 縮進

使用soft tab(4個空格)

.element {
    position: absolute;
    top: 10px;
    left: 10px;

    border-radius: 10px;
    width: 50px;
    height: 50px;
}
複製代碼

2)分號

每一個屬性聲明末尾都要加分號。

.element {
    width: 20px;
    height: 20px;

    background-color: red;
}
複製代碼

3)空格

如下幾種狀況不須要空格:

  • 屬性名後
  • 多個規則的分隔符','前
  • !important '!'後
  • 屬性值中'('後和')'前
  • 行末不要有多餘的空格

如下幾種狀況須要空格:

  • 屬性值前
  • 選擇器'>', '+', '~'先後
  • '{'前
  • !important '!'前
  • @else 先後
  • 屬性值中的','後
  • 註釋'/'後和'/'前
/* not good */
.element {
    color :red! important;
    background-color: rgba(0,0,0,.5);
}

/* good */
.element {
    color: red !important;
    background-color: rgba(0, 0, 0, .5);
}

/* not good */
.element ,
.dialog{
    ...
}

/* good */
.element,
.dialog {

}

/* not good */
.element>.dialog{
    ...
}

/* good */
.element > .dialog{
    ...
}

/* not good */
.element{
    ...
}

/* good */
.element {
    ...
}

/* not good */
@debug: true;

header {
  background-color: (yellow)when(@debug = true);
}


/* good */
header {
  background-color: (yellow) when (@debug = true);
}
複製代碼

4) 空行

如下幾種狀況須要空行:

  • 文件最後保留一個空行
  • '}'後最好跟一個空行,包括scss中嵌套的規則
  • 屬性之間須要適當的空行,具體見屬性聲明順序
/* not good */
.element {
    ...
}
.dialog {
    color: red;
    &:after {
        ...
    }
}

/* good */
.element {
    ...
}

.dialog {
    color: red;

    &:after {
        ...
    }
}
複製代碼

5) 註釋

註釋統一用'/* */'(scss中也不要用'//'),具體參照右邊的寫法;

縮進與下一行代碼保持一致;

可位於一個代碼行的末尾,與代碼間隔一個空格。

/* Modal header */
.modal-header {
    ...
}

/* * Modal header */
.modal-header {
    ...
}

.modal-header {
    /* 50px */
    width: 50px;

    color: red; /* color red */
}
複製代碼

6) 引號

最外層統一使用雙引號;

url的內容要用引號;

屬性選擇器中的屬性值須要引號。

.element:after {
    content: "";
    background-image: url("logo.png");
}

li[data-type="single"] {
    ...
}
複製代碼

7)命名

  • 類名使用小寫字母,以中劃線分隔
  • id採用駝峯式命名
  • less中的變量、函數以中劃線分隔命名
/* class */
.element-content {
    ...
}

/* id */
#myDialog {
    ...
}

/* 變量 */
@color-black: #000;

/* mixins */
.my-mixin() {
  color: black;
}

複製代碼

8)屬性聲明順序

相關的屬性聲明按右邊的順序作分組處理,組之間須要有一個空行。

.declaration-order {
    display: block;
    float: right;

    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 100;

    border: 1px solid #e5e5e5;
    border-radius: 3px;
    width: 100px;
    height: 100px;

    font: normal 13px "Helvetica Neue", sans-serif;
    line-height: 1.5;
    text-align: center;

    color: #333;
    background-color: #f5f5f5;

    opacity: 1;
}
複製代碼

書寫順序先後爲:

(1)定位屬性:position display float left top right bottom overflow clear z-index

(2)自身屬性:width height padding border margin background

(3)文字樣式:font-family font-size font-style font-weight font-varient color

(4)文本屬性text-align vertical-align text-wrap text-transform text-indent text-decoration letter-spacing word-spacing white-space text-overflow

目的:減小瀏覽器reflow(迴流),提高瀏覽器渲染dom的性能

原理:瀏覽器的渲染流程爲:

一、解析html構建dom樹,解析css構建css樹:將html解析成樹形的數據結構,將css解析成樹形的數據結構

二、構建render樹:DOM樹和CSS樹合併以後造成的render樹。

三、佈局render樹:有了render樹,瀏覽器已經知道那些網頁中有哪些節點,各個節點的css定義和以及它們的從屬關係,從而計算出每一個節點在屏幕中的位置。

四、繪製render樹:按照計算出來的規則,經過顯卡把內容畫在屏幕上。

css樣式解析到顯示至瀏覽器屏幕上就發生在234步驟,可見瀏覽器並非一獲取到css樣式就立馬開始解析而是根據css樣式的書寫順序將之按照dom樹的結構分佈render樣式,完成第2步,而後開始遍歷每一個樹結點的css樣式進行解析,此時的css樣式的遍歷順序徹底是按照以前的書寫順序。在解析過程當中,一旦瀏覽器發現某個元素的定位變化影響DOM,則須要從新渲染。

正確的書寫順序:

.demo{
    width: 100px;
	height: 100px;
	background-color: red ;
    
	position: absolute;
}
複製代碼

當瀏覽器解析到position的時候忽然發現該元素是絕對定位元素須要脫離文檔流,而以前倒是按照普通元素進行解析的,因此不得不從新渲染,解除該元素在文檔中所佔位置,然而因爲該元素的佔位發生變化,其餘元素也可能會受到它迴流的影響而從新排位。最終致使③步驟花費的時間過久而影響到④步驟的顯示,影響了用戶體驗。

// 下面是推薦的屬性的順序
[ [ "display", "visibility", "float", "clear", "overflow", "overflow-x", "overflow-y", "clip", "zoom" ],
    [ "table-layout", "empty-cells", "caption-side", "border-spacing", "border-collapse", "list-style", "list-style-position", "list-style-type", "list-style-image" ],
    [ "-webkit-box-orient", "-webkit-box-direction", "-webkit-box-decoration-break", "-webkit-box-pack", "-webkit-box-align", "-webkit-box-flex" ],
    [ "position", "top", "right", "bottom", "left", "z-index" ],
    [ "margin", "margin-top", "margin-right", "margin-bottom", "margin-left", "-webkit-box-sizing", "-moz-box-sizing", "box-sizing", "border", "border-width", "border-style", "border-color", "border-top", "border-top-width", "border-top-style", "border-top-color", "border-right", "border-right-width", "border-right-style", "border-right-color", "border-bottom", "border-bottom-width", "border-bottom-style", "border-bottom-color", "border-left", "border-left-width", "border-left-style", "border-left-color", "-webkit-border-radius", "-moz-border-radius", "border-radius", "-webkit-border-top-left-radius", "-moz-border-radius-topleft", "border-top-left-radius", "-webkit-border-top-right-radius", "-moz-border-radius-topright", "border-top-right-radius", "-webkit-border-bottom-right-radius", "-moz-border-radius-bottomright", "border-bottom-right-radius", "-webkit-border-bottom-left-radius", "-moz-border-radius-bottomleft", "border-bottom-left-radius", "-webkit-border-image", "-moz-border-image", "-o-border-image", "border-image", "-webkit-border-image-source", "-moz-border-image-source", "-o-border-image-source", "border-image-source", "-webkit-border-image-slice", "-moz-border-image-slice", "-o-border-image-slice", "border-image-slice", "-webkit-border-image-width", "-moz-border-image-width", "-o-border-image-width", "border-image-width", "-webkit-border-image-outset", "-moz-border-image-outset", "-o-border-image-outset", "border-image-outset", "-webkit-border-image-repeat", "-moz-border-image-repeat", "-o-border-image-repeat", "border-image-repeat", "padding", "padding-top", "padding-right", "padding-bottom", "padding-left", "width", "min-width", "max-width", "height", "min-height", "max-height" ],
    [ "font", "font-family", "font-size", "font-weight", "font-style", "font-variant", "font-size-adjust", "font-stretch", "font-effect", "font-emphasize", "font-emphasize-position", "font-emphasize-style", "font-smooth", "line-height", "text-align", "-webkit-text-align-last", "-moz-text-align-last", "-ms-text-align-last", "text-align-last", "vertical-align", "white-space", "text-decoration", "text-emphasis", "text-emphasis-color", "text-emphasis-style", "text-emphasis-position", "text-indent", "-ms-text-justify", "text-justify", "letter-spacing", "word-spacing", "-ms-writing-mode", "text-outline", "text-transform", "text-wrap", "-ms-text-overflow", "text-overflow", "text-overflow-ellipsis", "text-overflow-mode", "-ms-word-wrap", "word-wrap", "-ms-word-break", "word-break" ],
    [ "color", "background", "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader", "background-color", "background-image", "background-repeat", "background-attachment", "background-position", "-ms-background-position-x", "background-position-x", "-ms-background-position-y", "background-position-y", "-webkit-background-clip", "-moz-background-clip", "background-clip", "background-origin", "-webkit-background-size", "-moz-background-size", "-o-background-size", "background-size" ],
    [ "outline", "outline-width", "outline-style", "outline-color", "outline-offset", "opacity", "filter:progid:DXImageTransform.Microsoft.Alpha(Opacity", "-ms-filter:\\'progid:DXImageTransform.Microsoft.Alpha", "-ms-interpolation-mode", "-webkit-box-shadow", "-moz-box-shadow", "box-shadow", "filter:progid:DXImageTransform.Microsoft.gradient", "-ms-filter:\\'progid:DXImageTransform.Microsoft.gradient", "text-shadow" ],
    [ "-webkit-transition", "-moz-transition", "-ms-transition", "-o-transition", "transition", "-webkit-transition-delay", "-moz-transition-delay", "-ms-transition-delay", "-o-transition-delay", "transition-delay", "-webkit-transition-timing-function", "-moz-transition-timing-function", "-ms-transition-timing-function", "-o-transition-timing-function", "transition-timing-function", "-webkit-transition-duration", "-moz-transition-duration", "-ms-transition-duration", "-o-transition-duration", "transition-duration", "-webkit-transition-property", "-moz-transition-property", "-ms-transition-property", "-o-transition-property", "transition-property", "-webkit-transform", "-moz-transform", "-ms-transform", "-o-transform", "transform", "-webkit-transform-origin", "-moz-transform-origin", "-ms-transform-origin", "-o-transform-origin", "transform-origin", "-webkit-animation", "-moz-animation", "-ms-animation", "-o-animation", "animation", "-webkit-animation-name", "-moz-animation-name", "-ms-animation-name", "-o-animation-name", "animation-name", "-webkit-animation-duration", "-moz-animation-duration", "-ms-animation-duration", "-o-animation-duration", "animation-duration", "-webkit-animation-play-state", "-moz-animation-play-state", "-ms-animation-play-state", "-o-animation-play-state", "animation-play-state", "-webkit-animation-timing-function", "-moz-animation-timing-function", "-ms-animation-timing-function", "-o-animation-timing-function", "animation-timing-function", "-webkit-animation-delay", "-moz-animation-delay", "-ms-animation-delay", "-o-animation-delay", "animation-delay", "-webkit-animation-iteration-count", "-moz-animation-iteration-count", "-ms-animation-iteration-count", "-o-animation-iteration-count", "animation-iteration-count", "-webkit-animation-direction", "-moz-animation-direction", "-ms-animation-direction", "-o-animation-direction", "animation-direction" ],
    [ "content", "quotes", "counter-reset", "counter-increment", "resize", "cursor", "-webkit-user-select", "-moz-user-select", "-ms-user-select", "user-select", "nav-index", "nav-up", "nav-right", "nav-down", "nav-left", "-moz-tab-size", "-o-tab-size", "tab-size", "-webkit-hyphens", "-moz-hyphens", "hyphens", "pointer-events" ]
]
複製代碼

9)顏色

顏色16進制用小寫字母;

顏色16進制儘可能用簡寫。

/* not good */
.element {
    color: #ABCDEF;
    background-color: #001122;
}

/* good */
.element {
    color: #abcdef;
    background-color: #012;
}
複製代碼

10)屬性簡寫

屬性簡寫須要你很是清楚屬性值的正確順序,並且在大多數狀況下並不須要設置屬性簡寫中包含的全部值,因此建議儘可能分開聲明會更加清晰;

marginpadding 相反,須要使用簡寫;

常見的屬性簡寫包括:

  • font
  • background
  • transition
  • animation
/* not good */
.element {
    transition: opacity 1s linear 2s;
}

/* good */
.element {
    transition-delay: 2s;
    transition-timing-function: linear;
    transition-duration: 1s;
    transition-property: opacity;
}
複製代碼

11)媒體查詢

儘可能將媒體查詢的規則靠近與他們相關的規則,不要將他們一塊兒放到一個獨立的樣式文件中,或者丟在文檔的最底部,這樣作只會讓你們之後更容易忘記他們。

.element {
    ...
}

.element-avatar{
    ...
}

@media (min-width: 480px) {
    .element {
        ...
    }

    .element-avatar {
        ...
    }
}
複製代碼

12)Less相關

每一個模塊應該有一個單獨的less, 而後每一個最外層的父類 className 應該寫在第一位,全部子Node的樣式都寫在裏面,這樣是爲了不命名衝突。好比

//out: false
.parent-name{
    
    .child-name{
        ...
    }
    
    ...
}
複製代碼

@import 引入的文件不須要結尾的'.less'

LESS嵌套最多不能超過5層

不容許有空的規則;

元素選擇器用小寫字母;

去掉小數點前面的0;

去掉數字中沒必要要的小數點和末尾的0;

屬性值'0'後面不要加單位;

同個屬性不一樣前綴的寫法須要在垂直方向保持對齊,具體參照右邊的寫法;

無前綴的標準屬性應該寫在有前綴的屬性後面;

不要在同個規則裏出現重複的屬性,若是重複的屬性是連續的則不要緊;

不要在一個文件裏出現兩個相同的規則;

border: 0; 代替 border: none;

CSS選擇器不要超過3層

儘可能少用'*'選擇器。

/* not good */
.element {
}

/* not good */
LI {
    ...
}

/* good */
li {
    ...
}

/* not good */
.element {
    color: rgba(0, 0, 0, 0.5);
}

/* good */
.element {
    color: rgba(0, 0, 0, .5);
}

/* not good */
.element {
    width: 50.0px;
}

/* good */
.element {
    width: 50px;
}

/* not good */
.element {
    width: 0px;
}

/* good */
.element {
    width: 0;
}

/* not good */
.element {
    border-radius: 3px;
    -webkit-border-radius: 3px;
    -moz-border-radius: 3px;

    background: linear-gradient(to bottom, #fff 0, #eee 100%);
    background: -webkit-linear-gradient(top, #fff 0, #eee 100%);
    background: -moz-linear-gradient(top, #fff 0, #eee 100%);
}

/* good */
.element {
    -webkit-border-radius: 3px;
       -moz-border-radius: 3px;
            border-radius: 3px;

    background: -webkit-linear-gradient(top, #fff 0, #eee 100%);
    background:    -moz-linear-gradient(top, #fff 0, #eee 100%);
    background:         linear-gradient(to bottom, #fff 0, #eee 100%);
}

/* not good */
.element {
    color: rgb(0, 0, 0);
    width: 50px;
    color: rgba(0, 0, 0, .5);
}

/* good */
.element {
    color: rgb(0, 0, 0);
    color: rgba(0, 0, 0, .5);
}
複製代碼

5 JavaScript

1)縮進

使用soft tab(4個空格)。

var x = 1,
    y = 1;

if (x < y) {
    x += 10;
} else {
    x += 1;
}
複製代碼

2)分號

如下幾種狀況後需加分號:

  • 變量聲明
  • 表達式
  • return
  • throw
  • break
  • continue
  • do-while
/* var declaration */
var x = 1;

/* expression statement */
x++;

/* do-while */
do {
    x++;
} while (x < 10);
複製代碼

3)空格

如下幾種狀況不須要空格:

  • 對象的屬性名後
  • 前綴一元運算符後
  • 後綴一元運算符前
  • 函數調用括號前
  • 不管是函數聲明仍是函數表達式,'('前不要空格
  • 數組的'['後和']'前
  • 對象的'{'後和'}'前
  • 運算符'('後和')'前

如下幾種狀況須要空格:

  • 二元運算符先後
  • 三元運算符'?:'先後
  • 代碼塊'{'前
  • 下列關鍵字前:else, while, catch, finally
  • 下列關鍵字後:if, else, for, while, do, switch, case, try,catch, finally, with, return, typeof
  • 單行註釋'//'後(若單行註釋和代碼同行,則'//'前也須要),多行註釋'*'後
  • 對象的屬性值前
  • for循環,分號後留有一個空格,前置條件若是有多個,逗號後留一個空格
  • 不管是函數聲明仍是函數表達式,'{'前必定要有空格
  • 函數的參數之間
// not good
var a = {
    b :1
};

// good
var a = {
    b: 1
};

// not good
++ x;
y ++;
z = x?1:2;

// good
++x;
y++;
z = x ? 1 : 2;

// not good
var a = [ 1, 2 ];

// good
var a = [1, 2];

// not good
var a = ( 1+2 )*3;

// good
var a = (1 + 2) * 3;

// no space before '(', one space before '{', one space between function parameters
var doSomething = function(a, b, c) {
    // do something
};

// no space before '('
doSomething(item);

// not good
for(i=0;i<6;i++){
    x++;
}

// good
for (i = 0; i < 6; i++) {
    x++;
}
複製代碼

4)空行

如下幾種狀況須要空行:

  • 變量聲明後(當變量聲明在代碼塊的最後一行時,則無需空行)
  • 註釋前(當註釋在代碼塊的第一行時,則無需空行)
  • 代碼塊後(在函數調用、數組、對象中則無需空行)
  • 文件最後保留一個空行
// need blank line after variable declaration
var x = 1;

// not need blank line when variable declaration is last expression in the current block
if (x >= 1) {
    var y = x + 1;
}

var a = 2;

// need blank line before line comment
a++;

function b() {
    // not need blank line when comment is first line of block
    return a;
}

// need blank line after blocks
for (var i = 0; i < 2; i++) {
    if (true) {
        return false;
    }

    continue;
}

var obj = {
    foo: function() {
        return 1;
    },

    bar: function() {
        return 2;
    }
};

// not need blank line when in argument list, array, object
func(
    2,
    function() {
        a++;
    },
    3
);

var foo = [
    2,
    function() {
        a++;
    },
    3
];

var foo = {
    a: 2,
    b: function() {
        a++;
    },
    c: 3
};
複製代碼

5)換行

換行的地方,行末必須有','或者運算符;

如下幾種狀況不須要換行:

  • 下列關鍵字後:else, catch, finally
  • 代碼塊'{'前

如下幾種狀況須要換行:

  • 代碼塊'{'後和'}'前
  • 變量賦值後
// not good
var a = {
    b: 1
    , c: 2
};

x = y
    ? 1 : 2;

// good
var a = {
    b: 1,
    c: 2
};

x = y ? 1 : 2;
x = y ?
    1 : 2;

// no need line break with 'else', 'catch', 'finally'
if (condition) {
    ...
} else {
    ...
}

try {
    ...
} catch (e) {
    ...
} finally {
    ...
}

// not good
function test() {
    ...
}

// good
function test() {
    ...
}

// not good
var a, foo = 7, b,
    c, bar = 8;

// good
var a,
    foo = 7,
    b, c, bar = 8;
複製代碼

6)單行註釋

雙斜線後,必須跟一個空格;

縮進與下一行代碼保持一致;

可位於一個代碼行的末尾,與代碼間隔一個空格。

if (condition) {
    // if you made it here, then all security checks passed
    allowed();
}

var zhangsan = 'zhangsan'; // one space after code
複製代碼

7)多行註釋

最少三行, '*'後跟一個空格,具體參照右邊的寫法;

建議在如下狀況下使用:

  • 難於理解的代碼段
  • 可能存在錯誤的代碼段
  • 瀏覽器特殊的HACK代碼
  • 業務邏輯強相關的代碼
/* * one space after '*' */
var x = 1;
複製代碼

8)文檔註釋

各種標籤@param, @method等請參考usejsdocJSDoc Guide

建議在如下狀況下使用:

  • 全部常量
  • 全部函數
  • 全部類
/**
 * @func
 * @desc 一個帶參數的函數
 * @param {string} a - 參數a
 * @param {number} b=1 - 參數b默認值爲1
 * @param {string} c=1 - 參數c有兩種支持的取值</br>1—表示x</br>2—表示xx
 * @param {object} d - 參數d爲一個對象
 * @param {string} d.e - 參數d的e屬性
 * @param {string} d.f - 參數d的f屬性
 * @param {object[]} g - 參數g爲一個對象數組
 * @param {string} g.h - 參數g數組中一項的h屬性
 * @param {string} g.i - 參數g數組中一項的i屬性
 * @param {string} [j] - 參數j是一個可選參數
 */
function foo(a, b, c, d, g, j) {
    ...
}
複製代碼

9)引號

最外層統一使用單引號。

// not good
var x = "test";

// good
var y = 'foo',
    z = '<div id="test"></div>';
複製代碼

10)變量命名

  • 標準變量採用駝峯式命名(除了對象的屬性外,主要是考慮到cgi返回的數據)
  • 'ID'在變量名中全大寫
  • 'URL'在變量名中全大寫
  • 'Android'在變量名中大寫第一個字母
  • 'iOS'在變量名中小寫第一個,大寫後兩個字母
  • 常量全大寫,用下劃線鏈接
  • 構造函數,大寫第一個字母
  • jquery對象必須以'$'開頭命名
var thisIsMyName;

var goodID;

var reportURL;

var AndroidVersion;

var iOSVersion;

var MAX_COUNT = 10;

function Person(name) {
    this.name = name;
}

// not good
var body = $('body');

// good
var $body = $('body');
複製代碼

11)變量聲明

一個函數做用域中全部的變量聲明儘可能提到函數首部,用一個var 聲明,不容許出現兩個連續的var聲明。

function doSomethingWithItems(items) {
    // use one var
    var value = 10,
        result = value + 10,
        i,
        len;

    for (i = 0, len = items.length; i < len; i++) {
        result += 10;
    }
}
複製代碼

12)函數

不管是函數聲明仍是函數表達式,'('前不要空格,但'{'前必定要有空格;

函數調用括號前不須要空格;

當即執行函數外必須包一層括號;

不要給inline function命名;

參數之間用', '分隔,注意逗號後有一個空格。

// no space before '(', but one space before'{'
var doSomething = function(item) {
    // do something
};

function doSomething(item) {
    // do something
}

// not good
doSomething (item);

// good
doSomething(item);

// requires parentheses around immediately invoked function expressions
(function() {
    return 1;
})();

// not good
[1, 2].forEach(function x() {
    ...
});

// good
[1, 2].forEach(function() {
    ...
});

// not good
var a = [1, 2, function a() {
    ...
}];

// good
var a = [1, 2, function() {
    ...
}];

// use ', ' between function parameters
var doSomething = function(a, b, c) {
    // do something
};
複製代碼

13)數組、對象

對象屬性名不須要加引號;

對象以縮進的形式書寫,不要寫在一行;

數組、對象最後不要有逗號。

// not good
var a = {
    'b': 1
};

var a = {b: 1};

var a = {
    b: 1,
    c: 2,
};

// good
var a = {
    b: 1,
    c: 2
};
複製代碼

14)括號

下列關鍵字後必須有大括號(即便代碼塊的內容只有一行):if, else,for, while, do, switch, try, catch, finally, with

// not good
if (condition)
    doSomething();

// good
if (condition) {
    doSomething();
}
複製代碼

15)null

適用場景:

  • 初始化一個未來可能被賦值爲對象的變量
  • 與已經初始化的變量作比較
  • 做爲一個參數爲對象的函數的調用傳參
  • 做爲一個返回對象的函數的返回值

不適用場景:

  • 不要用null來判斷函數調用時有無傳參
  • 不要與未初始化的變量作比較
// not good
function test(a, b) {
    if (b `= null) { // not mean b is not supply ... } } var a; if (a `= null) {
    ...
}

// good
var a = null;

if (a `= null) { ... } 複製代碼

16)undefined

永遠不要直接使用undefined進行變量判斷;

使用typeof和字符串'undefined'對變量進行判斷。

// not good
if (person `= undefined) { ... } // good if (typeof person `= 'undefined') {
    ...
}
複製代碼

17)jshint

用'=', '!'代替'`', '!=';

for-in裏必定要有hasOwnProperty的判斷;

不要在內置對象的原型上添加方法,如Array, Date;

不要在內層做用域的代碼裏聲明瞭變量,以後卻訪問到了外層做用域的同名變量;

變量不要先使用後聲明;

不要在一句代碼中單單使用構造函數,記得將其賦值給某個變量;

不要在同個做用域下聲明同名變量;

不要在一些不須要的地方加括號,例:delete(a.b);

不要使用未聲明的變量(全局變量須要加到.jshintrc文件的globals屬性裏面);

不要聲明瞭變量卻不使用;

不要在應該作比較的地方作賦值;

debugger不要出如今提交的代碼裏;

數組中不要存在空元素;

不要在循環內部聲明函數;

不要像這樣使用構造函數,例:new function () { ... }, new Object

// not good
if (a ` 1) { a++; } // good if (a `= 1) {
    a++;
}

// good
for (key in obj) {
    if (obj.hasOwnProperty(key)) {
        // be sure that obj[key] belongs to the object and was not inherited
        console.log(obj[key]);
    }
}

// not good
Array.prototype.count = function(value) {
    return 4;
};

// not good
var x = 1;

function test() {
    if (true) {
        var x = 0;
    }

    x += 1;
}

// not good
function test() {
    console.log(x);

    var x = 1;
}

// not good
new Person();

// good
var person = new Person();

// not good
delete(obj.attr);

// good
delete obj.attr;

// not good
if (a = 10) {
    a++;
}

// not good
var a = [1, , , 2, 3];

// not good
var nums = [];

for (var i = 0; i < 10; i++) {
    (function(i) {
        nums[i] = function(j) {
            return i + j;
        };
    }(i));
}

// not good
var singleton = new function() {
    var privateVar;

    this.publicMethod = function() {
        privateVar = 1;
    };

    this.publicMethod2 = function() {
        privateVar = 2;
    };
};
複製代碼

18)雜項

不要混用tab和space;

不要在一處使用多個tab或space;

換行符統一用'LF';

對上下文this的引用只能使用'_this', 'that', 'self'其中一個來命名;

行尾不要有空白字符;

switch的falling through和no default的狀況必定要有註釋特別說明;

不容許有空的代碼塊。

// not good
var a   = 1;

function Person() {
    // not good
    var me = this;

    // good
    var _this = this;

    // good
    var that = this;

    // good
    var self = this;
}

// good
switch (condition) {
    case 1:
    case 2:
        ...
        break;
    case 3:
        ...
    // why fall through
    case 4
        ...
        break;
    // why no default
}

// not good with empty block
if (condition) {

}
複製代碼

插件推薦: EditorConfig for VS Code 生成.editorconfig文件

root = true

[*]
indent_style = space
indent_size = 4
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false
複製代碼

未完待續

相關文章
相關標籤/搜索