日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > HTML >内容正文

HTML

前端开发规范文档(html,css,js)

發布時間:2023/12/10 HTML 53 豆豆
生活随笔 收集整理的這篇文章主要介紹了 前端开发规范文档(html,css,js) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

首先吐槽一句,本來想上傳word文檔的,可是發現博客不能上傳word文檔,這就很尷尬了。

首先聲明該規范不是本人寫的,網上搜前端規范發現這個很詳細就先復制下來做筆記,當然不可能啥都按規范來,每個公司的規范都不一樣..僅供參考

?

前端開發規范文檔

?

Html規范

1 代碼風格

1.1 縮進

**【強制】**使用?4?個空格作為一個縮進層級,不允許使用?2?個空格或?tab?字符;

2 屬性

2.1 屬性引號

**【強制】**對于屬性的定義使用雙引號,不允許使用單引號,不允許不使用引號;

示例:

<!-- Not so great -->

<img class='avatar' src="./img/avatar.png" alt='avatar'>

?

<!-- Better -->

<img class="avatar" src="./img/avatar.png" alt="avatar">

2.2 屬性大小寫

**【強制】**屬性名應該小寫,不允許大寫或大小寫混合;

示例:

<!-- Not so great -->

<table cellSpacing="0">...</table>

?

<!-- Better -->

<table cellspacing="0">...</table>

2.3 屬性布爾值

**【建議】**布爾類型的屬性,建議不添加屬性值,至少同一項目要保持一致;

示例:

<input type="text" disabled>

<input type="checkbox" checked>

2.4 屬性聲明順序

**【建議】**HTML 屬性建議盡量按照以下給出的順序依次排列,確保代碼的易讀性。

  • class
  • id,?name
  • data-*
  • src,?for,?type,?href
  • title,?alt
  • aria-*,?role

class 用于標識高度可復用組件,因此應該排在首位。id 用于標識具體組件,應當謹慎使用(例如,頁面內的書簽),建議預留更多的id命名給技術,因此排在第二位。

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

?

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

?

<img src="..." alt="...">

2.5 自定義屬性

**【建議】**使用自定義屬性作為JS的hook,建議以data-為前綴;

示例:

<input data-role="getPic" type="button">

2.6 鏈接屬性

**【強制】**禁止?a?標簽的?href?取值為空或不寫?href?屬性,重構時默認可用?#?代替;

如果不需要使用鏈接功能,請不要使用不帶?href?的?a?標簽,既不符合標簽的語義,也可能會產生未知的兼容性問題;

示例:

<!-- Not so great -->

<a href="" title="title">歡聚時代</a>

<a class="xxx">歡聚時代</a>

?

<!-- Better -->

<a href="#" title="title">歡聚時代</a>

[?]

3 標簽

3.1 標簽大小寫

**【強制】**標簽名應該小寫,不允許大寫或大小寫混合;

示例:

<!-- Not so great -->

<DIV clsss="xxx">...</DIV>

?

<!-- Better -->

<div clsss="xxx">...</div>

3.2 標簽自閉合

**【建議】**對于無需自閉合的標簽,建議不自閉合,至少同一項目要保持一致;

常見無需自閉合標簽有input、img、br、hr等

示例:

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

3.3 標簽嵌套

**【強制】**標簽使用必須符合標簽嵌套規則;

例如:內聯元素不能嵌套塊元素,<p>元素和<h1~6>元素不能嵌套塊元素等,詳見?Allowed nesting of elements in HTML 4 Strict (and XHTML 1.0 Strict)?與?HTML5 Content models;

**【建議】**實用為王,盡量遵循 HTML 標準和語義,但是不要以犧牲實用性為代價。任何時候都要盡量使用最少的標簽并保持最小的復雜度。

<!-- Not so great -->

<span class="avatar">

? <img src="...">

</span>

?

<!-- Better -->

<img class="avatar" src="...">

3.4 避免過時標簽

**【強制】**不允許使用過時的舊標簽,請使用新標簽或者CSS代替:

  • acronym?→?abbr
  • applet?→?object
  • b?→?strong
  • dir?→?ul
  • strike?→?del
  • basefont
  • big
  • center
  • font
  • isindex
  • tt
  • u

請參詳:http://www.w3schools.com/tags/

[?]

4 head設定

4.1 doctype

**【強制】**doctype使用 HTML5 的 doctype 來啟用標準模式。

其中?doctype?建議使用大寫的 DOCTYPE;?關于doctype該使用大寫還是小寫的討論

示例:

<!DOCTYPE html>

4.2 頁面編碼

**【強制】**頁面必須明確指定字符編碼,讓瀏覽器快速確定適合網頁內容的渲染方式。指定字符編碼的 meta 必須是 head 的第一個直接子元素。建議使用無 BOM 的 UTF-8 編碼;

示例:

<meta charset="UTF-8">

4.3 兼容模式

**【建議】**PC端啟用 IE Edge 模式,并針對360瀏覽器啟用webkit渲染模式;

示例:

<meta http-equiv="X-UA-Compatible" content="IE=edge">

<meta name="renderer" content="webkit">

4.4 引入CSS

**【強制】**引入 CSS 時必須指明 rel="stylesheet";

建議在 head 中引入頁面需要的所有 CSS 資源,因為在頁面渲染的過程中,新的CSS可能導致元素的樣式重新計算和繪制,頁面閃爍;

示例:

<link rel="stylesheet" src="global.css">

4.5 引入JavaScript

**【建議】**JavaScript應當放在頁面尾部;出于性能方面的考慮,如非必要,請遵守此條建議;

示例:

<body>

??? <!-- a lot of elements -->

??? <script src="main.js"></script>

</body>

4.6 favicon

**【強制】**保證?favicon?可訪問;

在未指定 favicon 時,大多數瀏覽器會請求 Web Server 根目錄下的 favicon.ico 。為了保證favicon可訪問,避免404,必須遵循以下兩種方法之一:

  • 在 Web Server 根目錄放置 favicon.ico 文件;
  • 使用 link 指定 favicon;
  • 示例:

    <link type="image/x-icon" rel="shortcut icon" href="path/to/favicon.ico">

    附:工作流中默認的PChead設定

    <!DOCTYPE html>

    <html>

    <head>

    ??? <meta charset="UTF-8">

    ??? <meta http-equiv="X-UA-Compatible" content="IE=edge">

    ??? <meta name="renderer" content="webkit">

    ??? <meta name="viewport" content="width=device-width, initial-scale=1">

    ??? <meta name="Keywords" content="多玩游戲">

    ??? <meta name="description" content="多玩游戲">

    ??? <!-- a lot of elements -->

    </head>

    <body>

    ??? <!-- a lot of elements -->

    </body>

    </html>

    附:工作流中默認的移動端head設定

    <!DOCTYPE html>

    <html>

    <head>

    ??? <meta charset="UTF-8">

    ??? <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">

    ??? <meta name="format-detection" content="telephone=no,address=no,email=no">

    ??? <meta name="apple-itunes-app" content="app-id=myAppStoreID, affiliate-data=myAffiliateData, app-argument=myURL">

    ??? <meta name="keywords" content="多玩游戲">

    ??? <meta name="description" content="多玩游戲">

    ??? <!-- a lot of elements -->

    </head>

    <body>

    ??? <!-- a lot of elements -->

    </body>

    </html>

    注意:當該項目有相關的app在app store中,設置metaapple-itunes-app,如上面最后一條,并填上對應的app-id。詳細請看:Promoting Apps with Smart App Banners

    更詳細的meta屬性設置可以參詳:https://github.com/hzlzh/cool-head

    [?]

    5 圖片

    **【強制】**禁止?img?的?src?取值為空;延遲加載的圖片也要增加默認的?src;

    src?取值為空,會導致部分瀏覽器重新加載一次當前頁面,參考?Yahoo performance rules

    **【建議】**為重要圖片添加?alt?屬性;

    可以提高圖片加載失敗時的用戶體驗。

    **【建議】**添加?width?和?height?屬性,以避免頁面抖動;

    **【建議】**有下載需求或者預期會靈活變動的圖片采用?img?標簽實現,無下載需求的圖片采用 CSS 背景圖實現;

    • 用戶頭像、用戶產生的圖片等有潛在下載需求的圖片,以 img 形式實現,能方便用戶下載;
    • 無下載需求的圖片,比如:icon、背景、代碼使用的圖片等,盡可能采用 css 背景圖實現。

    [?]

    6 表單

    **【強制】**有文本標題的控件必須使用?label?標簽將其與其標題相關聯;

    有兩種方式:

  • 將控件置于 label 內;
  • label 的 for 屬性指向控件的 id。
  • 推薦使用第一種,減少不必要的 id。如果 DOM 結構不允許直接嵌套,則應使用第二種。

    示例:

    <label><input name="confirm" type="checkbox" value="on"> 我已確認上述條款</label>

    ?

    <label for="username">用戶名:</label> <input id="username" name="username" type="checkbox">

    **【建議】**盡量不要使用按鈕類元素的 name 屬性;

    由于瀏覽器兼容性問題,使用按鈕的 name 屬性會帶來許多難以發現的問題。具體情況可參考?此文;

    **【建議】**在針對移動設備開發的頁面時,根據內容類型指定輸入框的?type?屬性;

    根據內容類型指定輸入框類型,能獲得能友好的輸入體驗。

    示例:

    <input type="number" value="1">

    [?]

    7 注釋

    【建議】對超過10的頁面模塊進行注釋, 以降低開發人員的嵌套成本和后期的維護成本。建議使用結尾注釋方式,例如:

    當模塊代碼量較少時,可以省略?start。

    <!-- 文章內容 start -->

    <section id="post">

    ?? do some things...

    </section>

    <!-- 文章內容 end -->

    或者標注模塊的class或者id:

    <!-- #post start -->

    <section id="post">

    ??? do some things...

    </section>

    <!-- #post end -->

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    CSS規范

    1 命名規范

    該命名規范主要解決以下問題:

    • 從類名可以清晰區分出其功能作用,使頁面結構清晰【命名空間、標識符】;
    • 以組件、模塊的思想去寫一個區塊的結構,強化結構的模塊化【BEM模塊思想、基類、子類、擴展類】;
    • 減少多人合作、項目耦合等情況下的命名沖突【命名空間】;

    1.1 命名思想

    【強制】?區塊、模塊、組件等一個整個的結構遵循BEM命名思想;

    當你能確定組件內最后一級的結構不會再發生變化時,最后一級可省略類名,使用兩層嵌套;

    • .block?代表了更高級別的抽象或組件;
    • .block__element?代表.block的后代,用于形成一個完整的.block的整體;
    • .is-?|?.has-?|?.ext-?代表.block的修飾符,不使用雙中劃線--

    相關鏈接:

    • BEM—源自Yandex的CSS 命名方法論
    • BEM官網

    1.2 多單詞連接

    【強制】?(所有的)多個單詞使用小駝峰式命名,不允許使用中劃線或者下劃線連接多個單詞;

    多個單詞使用小駝峰式命名,以提升名稱的識別度,例如:newsList;

    1.3 命名空間

    【強制】?在合適的地方使用命名空間;

    • 布局:以g為命名空間,例如:.g-wrap?、.g-header、.g-content、.g-mian、.g-aside?等;
    • 工具:以u為命名空間,表示不耦合業務邏輯的、可復用的的工具,例如:.u-clearfix、.u-ellipsis?等;
    • 狀態:以is為命名空間,表示動態的、具有交互性質的狀態,例如:.is-open、.is-active、.is-selected?等;
    • 組件:以ui或者mod為命名空間,表示可復用、移植的組件模塊,例如:.ui-slider、.mod-dropMenu等;
    • 擴展:以ext為命名空間,表示對組件基類的視覺形態的擴展,例如:.ext-cover、、.ext-alignLeft?等;

    狀態類或擴展類一般出現在組件的父級節點,并且不允許單獨使用。舉個例子,同一個頁面有可能會在不同的地方都會使用is-active,并且每個is-active所操縱的節點的是不同的,所以要使用.ui-userCard.is-active??.ui-userCard .is-active來定義

    1.4 圖片命名

    • 圖標:以ico作為命名空間,例如:.ico-close?等;
    • LOGO:以logo作為命名空間,例如:.logo-duowan?等;
    • 內容圖像:以img作為命名空間,例如:.img-userGuide?等;

    1.5 區塊命名

    【推薦】?一般區塊都可以劃分為頭部、身體和尾部,因此建議給你的區塊分別以?hd、bd、ft來劃分;

    示例:

    .ui-card__hd {

    ??? margin: 0;

    }

    ?

    .ui-card__bd {

    ??? margin: 0;

    }

    ?

    .ui-card__ft {

    ??? margin: 0;

    }

    附:命名示例

    ?

    [?]

    2 代碼風格

    2.1 縮進

    【強制】?使用?4?個空格做為一個縮進層級,不允許使用?2?個空格 或?tab?字符;

    示例:

    /* Not so great */

    .selector {

    ? margin: 0;

    }

    ?

    /* Better */

    .selector {

    ??? margin: 0;

    }

    2.2 空格

    【強制】?選擇器 與?{之間必須包含空格;

    示例:

    /* Not so great */

    .selector{

    }

    ?

    /* Better */

    .selector {

    }

    【強制】?>、+、~?選擇器的兩邊各保留一個空格;

    示例:

    /* Not so great */

    main>nav {

    ??? padding: 10px;

    }

    label+input {

    ??? margin-left: 5px;

    }

    input:checked~button {

    ??? background-color: #69C;

    }

    ?

    /* Better */

    main > nav {

    ??? padding: 10px;

    }

    label + input {

    ??? margin-left: 5px;

    }

    input:checked ~ button {

    ??? background-color: #69C;

    }

    【強制】?屬性名 與之后的?:?之間不允許包含空格,?:與 屬性值 之間必須包含空格;

    示例:

    /* Not so great */

    margin :0;

    ?

    /* Better */

    margin: 0;

    【強制】?列表型屬性值 書寫在單行時,,后必須跟一個空格;

    示例:

    /* Not so great */

    font-family: Arial,sans-serif;

    box-shadow: 0 0 2px rgba(0,128,0,.3);

    ?

    /* Better */

    font-family: Arial, sans-serif;

    box-shadow: 0 0 2px rgba(0, 128, 0, .3);

    2.3 選擇器

    【強制】?當一個 rule 包含多個 selector 時,每個選擇器聲明必須獨占一行;

    示例:

    /* Not so great */

    .post, .page, .comment {

    ??? line-height: 1.5;

    }

    ?

    /* Better */

    .post,

    .page,

    .comment {

    ??? line-height: 1.5;

    }

    2.4 屬性

    【強制】?屬性定義必須另起一行;

    示例:

    /* Not so great */

    .selector { margin: 0; padding: 0;}

    ?

    /* Better */

    .selector {

    ??? margin: 0;

    ??? padding: 0;

    }

    【強制】?屬性定義后必須以分號結尾;

    示例:

    /* Not so great */

    .selector {

    ??? margin: 0

    }

    ?

    /* Better */

    .selector {

    ??? margin: 0;

    }

    [?]

    3. 通用

    3.1 選擇器

    【強制】?如無必要,不得為id、class選擇器添加?類型選擇器?進行限定;

    在性能和維護性上,都有一定的影響。

    示例:

    /* Not so great */

    dialog#error,

    p.danger-message {

    ??? font-color: #c00;

    }

    ?

    /* Better */

    #error,

    .danger-message {

    ??? font-color: #c00;

    }

    【建議】?選擇器的嵌套層級應該不大于?3?級,位置靠后的限定條件應可能精確;

    在性能和維護性上,都有一定的影響。

    示例:

    /* Not so great */

    .comment ul li a span {}

    #top-hero .hero-avatar li.avatar .pic em {}

    ?

    /* Better */

    .comment .date {}

    #top-hero .pic em {}

    3.2 屬性

    3.2.1 屬性書寫順序

    【建議】?同一 rule set 下的屬性在書寫時,應按功能進行分組,并以 Formatting Model > Box Model > Typographic > Visual 的順序書寫,以提高代碼的可讀性。

  • Positioning Model 布局方式、位置;相關屬性包括:position / top / right / bottom / left / z-index / display / float / ...
  • Box model 盒模型;相關屬性包括:width / height / padding / margin / border / overflow / ...
  • Typographic 文本排版;相關屬性包括:font / line-height / text-align / word-wrap / ...
  • Visual 視覺外觀;相關屬性包括:color / background / list-style / transform / animation / transition / ...
  • 如果包含 content 屬性,應放在最前面;
  • Positioning 處在第一位,因為他可以使一個元素脫離正常文本流,并且覆蓋盒模型相關的樣式。盒模型緊跟其后,因為他決定了一個組件的大小和位置。其他屬性只在組件 內部 起作用或者不會對前面兩種情況的結果產生影響,所以他們排在后面。

    詳情資料?Twitter的strictPropertyOrder

    3.2.2 屬性引號

    【強制】?屬性選擇器中的值必須用雙引號包圍。不允許使用單引號,不允許不使用引號。

    示例:

    /* Not so great */

    article[character='juliet'] {

    ??? voice-family: "Vivien Leigh", victoria, female

    }

    ?

    /* Better */

    article[character="juliet"] {

    ??? voice-family: "Vivien Leigh", victoria, female

    }

    3.2.3 屬性簡寫

    簡寫形式可以在一定程度上壓縮樣式,但并不意味著你可以對所有可以簡寫的屬性聲明都使用簡寫。過度使用簡寫形式的屬性聲明會導致代碼混亂,會對屬性值帶來不必要的覆蓋從而引起意外的副作用,并且不能充分利用CSS的繼承。常見的濫用簡寫屬性聲明的情況如下:

    • padding
    • margin
    • font
    • background
    • border
    • border-radius

    如果你只需定義其中的一兩個屬性,而不是全部,盡量分開來寫:

    /* Better */

    .selector {

    ??? margin-bottom: 10px;

    ??? background-color: red;

    ??? background-image: url(image.jpg);

    ??? border-top-left-radius: 3px;

    ??? border-top-right-radius: 3px;

    }

    ?

    /* Not so great */

    .selector {

    ??? margin: 0 0 10px;

    ??? background: red;

    ??? background: url(image.jpg);

    ??? border-radius: 3px 3px 0 0;

    }

    [?]

    4 值與單位

    4.1 文本

    【強制】?文本內容必須用雙引號包圍,不允許使用單引號;

    文本類型的內容可能在選擇器、屬性值等內容中。

    示例:

    /* Not so great */

    html[lang|=zh] q:before {

    ??? font-family: 'Microsoft YaHei', sans-serif;

    ??? content: '“';

    }

    ?

    /* Better */

    html[lang|="zh"] q:after {

    ??? font-family: "Microsoft YaHei", sans-serif;

    ??? content: "“";

    }

    4.2 數值

    【強制】?當數值為?0 - 1?之間的小數時,省略整數部分的?0

    示例:

    /* Not so great */

    .selector {

    ??? opacity: 0.8;

    }

    ?

    /* Better */

    .selector {

    ??? opacity: .8;

    }

    4.3 長度

    【強制】?長度為?0?時須省略單位 (也只有長度單位可省);

    示例:

    /* Not so great */

    .selector {

    ??? margin: 0px 10px;

    }

    ?

    /* Better */

    .selector {

    ??? margin: 0 10px;

    }

    4.4 url()

    【強制】?url() 函數中的路徑不加引號;

    示例:

    /* Not so great */

    .selector {

    ??? background: url("bg.png");

    }

    ?

    /* Better */

    .selector {

    ??? background: url(bg.png);

    }

    4.5 顏色

    【強制】?RGB顏色值必須使用十六進制記號形式?#rrggbb,不允許使用?rgb(),帶有alpha的顏色信息可以使用?rgba();顏色值不允許使用命名色值;

    示例:

    /* Not so great */

    .selector {

    ??? box-shadow: 0 0 2px rgba(0,128,0,.3);

    ??? border-color: rgb(0, 128, 0);

    ??? color: gray;

    }

    ?

    /* Better */

    .selector {

    ??? box-shadow: 0 0 2px rgba(0, 128, 0, .3);

    ??? border-color: #008000;

    ??? color: #999;

    }

    【建議】?顏色值中的英文字符采用小寫,至少要保證同一項目內一致;

    示例:

    /* Not so great */

    .selector {

    ??? color: #0073AA;

    }

    ?

    /* Better */

    .selector {

    ??? color: #0073aa;

    }

    4.6 2D位置

    【強制】?必須同時給出水平和垂直方向的位置;

    2D 位置初始值為 0% 0%,但在只有一個方向的值時,另一個方向的值會被解析為 center。為避免理解上的困擾,應同時給出兩個方向的值。?background-position屬性值的定義

    示例:

    /* Not so great */

    .selector {

    ??? background-position: top; /* 50% 0% */

    }

    ?

    /* Better */

    .selector {

    ??? background-position: center top; /* 50% 0% */

    }

    [?]

    5. 文本排版

    5.1 字體族

    【強制】?font-family?屬性中的字體族名稱應使用字體的英文?Family Name,其中如有空格,須放置在引號中;

    常見的字體族名稱如下:

    字體

    操作系統

    Family Name

    宋體 (中易宋體)

    Windows

    SimSun

    黑體 (中易黑體)

    Windows

    SimHei

    微軟雅黑

    Windows

    Microsoft YaHei

    微軟正黑

    Windows

    Microsoft JhengHei

    華文黑體

    Mac/iOS

    STHeiti

    冬青黑體

    Mac/iOS

    Hiragino Sans GB

    文泉驛正黑

    Linux

    WenQuanYi Zen Hei

    文泉驛微米黑

    Linux

    WenQuanYi Micro Hei

    【強制】?font-family?應當遵循以下順序:

  • 西文字體在前,中文字體在后;
  • 效果佳 (質量高/更能滿足需求) 的字體在前,效果一般的字體在后的順序編寫;
  • 最后必須指定一個通用字體族( serif / sans-serif );
  • 詳細說明可參考?如何保證網頁的字體在各平臺都盡量顯示為最高質量的黑體?

    【強制】?font-family?不區分大小寫,但在同一個項目中,同樣的 Family Name 大小寫必須統一;

    示例:

    /* Not so great */

    body {

    ??? font-family: arial, sans-serif;

    }

    ?

    h1 {

    ??? font-family: Arial, "Microsoft YaHei", sans-serif;

    }

    ?

    /* Better */

    body {

    ??? font-family: Arial, sans-serif;

    }

    ?

    h1 {

    ??? font-family: Arial, "Microsoft YaHei", sans-serif;

    }

    5.2 字重

    【強制】?font-weight?屬性必須使用數值方式描述;

    CSS 的字重分 100 – 900 共九檔,但目前受字體本身質量和瀏覽器的限制,實際上支持 400 和 700 兩檔,分別等價于關鍵詞 normal 和 bold。

    瀏覽器本身使用一系列啟發式規則來進行匹配,在 >700 時一般匹配字體的 Regular 字重,>=700 時匹配 Bold 字重。

    但已有瀏覽器開始支持 =600 時匹配 Semibold 字重 (見此表),故使用數值描述增加了靈活性,也更簡短。

    示例:

    /* Not so great */

    .selector {

    ??? font-weight: bold;

    }

    ?

    /* Better */

    .selector {

    ??? font-weight: 700;

    }

    [?]

    6 變換與動畫

    【強制】?使用?transition?定義屬性時應遵循以下順序:

  • [ transition-property ]:檢索或設置對象中的參與過渡的屬性;
  • [ transition-duration ]:檢索或設置對象過渡的持續時間;
  • [ transition-timing-function ]:檢索或設置對象中過渡的動畫類型;
  • [ transition-delay ]:檢索或設置對象延遲過渡的時間;
  • transition:[ transition-property ] || [ transition-duration ] || [ transition-timing-function ] || [ transition-delay ]

    如果順序錯亂,在某些安卓瀏覽器上會讓動畫失效。

    示例:

    /* Not so great */

    .selector {

    ??? transition: color .2s 0 ease-in;

    }

    ?

    /* Better */

    .selector {

    ??? transition: color .2s ease-in 0;

    }

    【建議】?盡可能在瀏覽器能高效實現的屬性上添加過渡和動畫:

    在可能的情況下應選擇這樣四種變換:

    • transform: translate(npx, npx);
    • transform: scale(n);
    • transform: rotate(ndeg);
    • opacity: 0..1;

    詳見?High Performance Animations

    [?]

    7 媒體查詢

    【強制】?Media Query?不得單獨編排,必須與相關的規則一起定義;

    不要將他們一起放到一個獨立的樣式文件中,或者丟在文檔的最底部,這樣做只會讓大家以后更容易忘記他們。

    示例:

    /* Not so great */

    /* header styles */

    /* main styles */

    /* footer styles */

    ?

    @media (...) {

    ??? /* header styles */

    ??? /* main styles */

    ??? /* footer styles */

    }

    ?

    /* Better */

    /* header styles */

    @media (...) {

    ??? /* header styles */

    }

    ?

    /* main styles */

    @media (...) {

    ??? /* main styles */

    }

    ?

    /* footer styles */

    @media (...) {

    ??? /* footer styles */

    }

    8 兼容性

    8.1 屬性前綴

    【強制】?帶私有前綴的屬性由長到短排列,按冒號位置對齊;

    標準屬性放在最后,按冒號對齊方便閱讀與編輯。

    示例:

    /* Not so great */

    .selector {

    ??? transition: color .2s ease-in 0;

    ??? -webkit-transition: color .2s ease-in 0;

    ??? -moz-transition: color .2s ease-in 0;

    }

    ?

    /* Better */

    .selector {

    ??? -webkit-transition: color .2s ease-in 0;

    ?????? -moz-transition: color .2s ease-in 0;

    ??????????? transition: color .2s ease-in 0;

    }

    8.2 hack

    【建議】?如果有其他解決方案,請不要使用hack;

    [?]

    9 代碼注釋

    代碼是由人編寫并維護的。請確保你的代碼能夠自描述、注釋良好并且易于他人理解。好的代碼注釋能夠傳達上下文關系和代碼目的。不要簡單地重申組件或 class 名稱。

    9.1 單行注釋

    【強制】?星號與內容之間必須保留一個空格;

    示例:

    /* 新聞中心表格隔行變色 */

    9.2 多行注釋

    【強制】?星號要一列對齊,星號與內容之間必須保留一個空格;

    示例:

    /**

    ?* Sometimes you need to include optional context for the entire component. Do that up here if it's important enough.

    ?*/

    9.3 文件注釋

    【強制】?文件頂部必須包含文件注釋,用?@file?標識文件說明。星號要一列對齊,星號與內容之間必須保留一個空格,標識符冒號與內容之間必須保留一個空格;

    /**

    ?* @file: 文件概要描述

    ?* @author: author-name(mail-name@domain.com)

    ?*????????? author-name2(mail-name2@domain.com)

    ?* @update: 2015-04-29 00:02:45

    ?*/

    • @update為可選項,建議每次改動都更新一下;
    • 當該業務項目主要由固定的一個或多個人負責時,需要添加@author標識,一方面是尊重勞動成果,另一方面方便在需要時快速定位責任人;

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    Js規范

    1 前言

    本文檔的目標是使JavaScript代碼風格保持一致,容易被理解和被維護。雖然本文檔是針對JavaScript設計的,但是在使用各種JavaScript的預編譯語言時(如TypeScript等)時,適用的部分也應盡量遵循本文檔的約定。

    2 代碼風格

    2.1 文件

    【建議】?JavaScript?文件使用無?BOM?的?UTF-8?編碼。

    解釋:

    UTF-8 編碼具有更廣泛的適應性。BOM 在使用程序或工具處理文件時可能造成不必要的干擾。

    【建議】?在文件結尾處,保留一個空行。

    2.2 結構**【強制】**

    2.2.1 縮進

    【強制】?使用?4?個空格做為一個縮進層級,不允許使用?2?個空格 或?tab?字符。
    【強制】?switch?下的?case?和?default?必須增加一個縮進層級。

    示例:

    // good switch (variable) { ? ??? case '1': ??????? // do... ??????? break; ? ??? case '2': ??????? // do... ??????? break; ? ??? default: ??????? // do... ? } ? // bad switch (variable) { ? case '1': ??? // do... ??? break; ? case '2': ??? // do... ??? break; ? default: ??? // do... ? }

    2.2.2 空格

    【強制】?二元運算符兩側必須有一個空格,一元運算符與操作對象之間不允許有空格。

    示例:

    var a = !arr.length; a++; a = b + c;
    【強制】?用作代碼塊起始的左花括號?{?前必須有一個空格。

    示例:

    // good if (condition) { } ? while (condition) { } ? function funcName() { } ? // bad if (condition){ } ? while (condition){ } ? function funcName(){ }
    【強制】?if / else / for / while / function / switch / do / try / catch / finally?關鍵字后,必須有一個空格。

    示例:

    // good if (condition) { } ? while (condition) { } ? (function () { })(); ? // bad if(condition) { } ? while(condition) { } ? (function() { })();
    【強制】?在對象創建時,屬性中的?:?之后必須有空格,:?之前不允許有空格。

    示例:

    // good var obj = { ??? a: 1, ??? b: 2, ??? c: 3 }; ? // bad var obj = { ??? a : 1, ??? b:2, ??? c :3 };
    【強制】?函數聲明、具名函數表達式、函數調用中,函數名和?(?之間不允許有空格。

    示例:

    // good function funcName() { } ? var funcName = function funcName() { }; ? funcName(); ? // bad function funcName () { } ? var funcName = function funcName () { }; ? funcName ();
    【強制】?,?和?;?前不允許有空格。

    示例:

    // good callFunc(a, b); ? // bad callFunc(a , b) ;
    【強制】?在函數調用、函數聲明、括號表達式、屬性訪問、if / for / while / switch / catch?等語句中,()?和?[]內緊貼括號部分不允許有空格。

    示例:

    // good ? callFunc(param1, param2, param3); ? save(this.list[this.indexes[i]]); ? needIncream && (variable += increament); ? if (num > list.length) { } ? while (len--) { } ? ? // bad ? callFunc( param1, param2, param3 ); ? save( this.list[ this.indexes[ i ] ] ); ? needIncreament && ( variable += increament ); ? if ( num > list.length ) { } ? while ( len-- ) { }
    【強制】?單行聲明的數組與對象,如果包含元素,{}?和?[]?內緊貼括號部分不允許包含空格。

    解釋:

    聲明包含元素的數組與對象,只有當內部元素的形式較為簡單時,才允許寫在一行。元素復雜的情況,還是應該換行書寫。

    示例:

    // good var arr1 = []; var arr2 = [1, 2, 3]; var obj1 = {}; var obj2 = {name: 'obj'}; var obj3 = { ??? name: 'obj', ??? age: 20, ??? sex: 1 }; ? // bad var arr1 = [ ]; var arr2 = [ 1, 2, 3 ]; var obj1 = { }; var obj2 = { name: 'obj' }; var obj3 = {name: 'obj', age: 20, sex: 1};
    【強制】?行尾不得有多余的空格。

    2.2.3 換行

    【強制】?每個獨立語句結束后必須換行。
    【強制】?每行不得超過?120?個字符。

    解釋:

    超長的不可分割的代碼允許例外,比如復雜的正則表達式。長字符串不在例外之列。

    【強制】?運算符處換行時,運算符必須在新行的行首。

    示例:

    // good if (user.isAuthenticated() ??? && user.isInRole('admin') ??? && user.hasAuthority('add-admin') ??? || user.hasAuthority('delete-admin') ) { ??? // Code } ? var result = number1 + number2 + number3 ??? + number4 + number5; ? ? // bad if (user.isAuthenticated() && ??? user.isInRole('admin') && ??? user.hasAuthority('add-admin') || ??? user.hasAuthority('delete-admin')) { ??? // Code } ? var result = number1 + number2 + number3 + ??? number4 + number5;
    【強制】?在函數聲明、函數表達式、函數調用、對象創建、數組創建、for語句等場景中,不允許在?,?或?;?前換行。

    示例:

    // good var obj = { ??? a: 1, ??? b: 2, ??? c: 3 }; ? foo( ??? aVeryVeryLongArgument, ??? anotherVeryLongArgument, ??? callback ); ? ? // bad var obj = { ??? a: 1 ??? , b: 2 ??? , c: 3 }; ? foo( ??? aVeryVeryLongArgument ??? , anotherVeryLongArgument ??? , callback );
    【建議】?不同行為或邏輯的語句集,使用空行隔開,更易閱讀。

    示例:

    // 僅為按邏輯換行的示例,不代表setStyle的最優實現 function setStyle(element, property, value) { ??? if (element == null) { ??????? return; ??? } ? ??? element.style[property] = value; }
    【建議】?在語句的行長度超過?120?時,根據邏輯條件合理縮進。

    示例:

    // 較復雜的邏輯條件組合,將每個條件獨立一行,邏輯運算符放置在行首進行分隔,或將部分邏輯按邏輯組合進行分隔。 // 建議最終將右括號 ) 與左大括號 { 放在獨立一行,保證與 if 內語句塊能容易視覺辨識。 if (user.isAuthenticated() ??? && user.isInRole('admin') ??? && user.hasAuthority('add-admin') ??? || user.hasAuthority('delete-admin') ) { ??? // Code } ? // 按一定長度截斷字符串,并使用 + 運算符進行連接。 // 分隔字符串盡量按語義進行,如不要在一個完整的名詞中間斷開。 // 特別的,對于HTML片段的拼接,通過縮進,保持和HTML相同的結構。 var html = '' // 此處用一個空字符串,以便整個HTML片段都在新行嚴格對齊 ??? + '<article>' ??? +???? '<h1>Title here</h1>' ??? +???? '<p>This is a paragraph</p>' ??? +???? '<footer>Complete</footer>' ??? + '</article>'; ? // 也可使用數組來進行拼接,相對 + 更容易調整縮進。 var html = [ ??? '<article>', ??????? '<h1>Title here</h1>', ??????? '<p>This is a paragraph</p>', ??????? '<footer>Complete</footer>', ??? '</article>' ]; html = html.join(''); ? // 當參數過多時,將每個參數獨立寫在一行上,并將結束的右括號 ) 獨立一行。 // 所有參數必須增加一個縮進。 foo( ??? aVeryVeryLongArgument, ??? anotherVeryLongArgument, ??? callback ); ? // 也可以按邏輯對參數進行組合。 // 最經典的是baidu.format函數,調用時將參數分為“模板”和“數據”兩塊 baidu.format( ??? dateFormatTemplate, ??? year, month, date, hour, minute, second ); ? // 當函數調用時,如果有一個或以上參數跨越多行,應當每一個參數獨立一行。 // 這通常出現在匿名函數或者對象初始化等作為參數時,如setTimeout函數等。 setTimeout( ??? function () { ??????? alert('hello'); ??? }, ??? 200 ); ? order.data.read( ??? 'id=' + me.model.id, ????function (data) { ??????? me.attchToModel(data.result); ??????? callback(); ??? }, ????300 ); ? // 鏈式調用較長時采用縮進進行調整。 $('#items') ??? .find('.selected') ??? .highlight() ??? .end(); ? // 三元運算符由3部分組成,因此其換行應當根據每個部分的長度不同,形成不同的情況。 var result = thisIsAVeryVeryLongCondition ??? ? resultA : resultB; ? var result = condition ??? ? thisIsAVeryVeryLongResult ??? : resultB; ? // 數組和對象初始化的混用,嚴格按照每個對象的 { 和結束 } 在獨立一行的風格書寫。 var array = [ ??? { ??????? // ... ??? }, ??? { ??????? // ... ??? } ];
    【建議】?對于?if...else...、try...catch...finally?等語句,推薦使用在?}?號后添加一個換行 的風格,使代碼層次結構更清晰,閱讀性更好。

    示例:

    if (condition) { ??? // some statements; } else { ??? // some statements; } ? try { ??? // some statements; } catch (ex) { ??? // some statements; }

    2.2.4 語句

    【強制】?不得省略語句結束的分號。
    【強制】?在?if / else / for / do / while?語句中,即使只有一行,也不得省略塊?{...}。

    示例:

    // good if (condition) { ??? callFunc(); } ? // bad if (condition) callFunc(); if (condition) ??? callFunc();
    【強制】?函數定義結束不允許添加分號。

    示例:

    // good function funcName() { } ? // bad function funcName() { }; ? // 如果是函數表達式,分號是不允許省略的。 var funcName = function () { };
    【強制】?IIFE?必須在函數表達式外添加?(,非?IIFE?不得在函數表達式外添加?(。

    解釋:

    IIFE = Immediately-Invoked Function Expression.

    額外的 ( 能夠讓代碼在閱讀的一開始就能判斷函數是否立即被調用,進而明白接下來代碼的用途。而不是一直拖到底部才恍然大悟。

    示例:

    // good var task = (function () { ?? // Code ?? return result; })(); ? var func = function () { }; ? ? // bad var task = function () { ??? // Code ??? return result; }(); ? var func = (function () { });

    2.3 命名

    【強制】?變量?使用?Camel命名法。

    示例:

    var loadingModules = {};
    【強制】?常量?使用?全部字母大寫,單詞間下劃線分隔?的命名方式。

    示例:

    var HTML_ENTITY = {};
    【強制】?函數?使用?Camel命名法。

    示例:

    function stringFormat(source) { }
    【強制】?函數的?參數?使用?Camel命名法。

    示例:

    function hear(theBells) { }
    【強制】?類?使用?Pascal命名法。

    示例:

    function TextNode(options) { }
    【強制】?類的?方法 / 屬性?使用?Camel命名法。

    示例:

    function TextNode(value, engine) { ??? this.value = value; ??? this.engine = engine; } ? TextNode.prototype.clone = function () { ??? return this; };
    【強制】?枚舉變量?使用?Pascal命名法,枚舉的屬性?使用?全部字母大寫,單詞間下劃線分隔?的命名方式。

    示例:

    var TargetState = { ??? READING: 1, ??? READED: 2, ??? APPLIED: 3, ??? READY: 4 };
    【強制】?命名空間?使用?Camel命名法。

    示例:

    equipments.heavyWeapons = {};
    【強制】?由多個單詞組成的縮寫詞,在命名中,根據當前命名法和出現的位置,所有字母的大小寫與首字母的大小寫保持一致。

    示例:

    function XMLParser() { } ? function insertHTML(element, html) { } ? var httpRequest = new HTTPRequest();
    【強制】?類名?使用?名詞。

    示例:

    function Engine(options) { }
    【建議】?函數名?使用?動賓短語。

    示例:

    function getStyle(element) { }
    【建議】?boolean?類型的變量使用?is?或?has?開頭。

    示例:

    var isReady = false; var hasMoreCommands = false;
    【建議】?Promise對象?用?動賓短語的進行時?表達。

    示例:

    var loadingData = ajax.get('url'); loadingData.then(callback);

    2.4 注釋

    2.4.1 單行注釋

    【強制】?必須獨占一行。//?后跟一個空格,縮進與下一行被注釋說明的代碼一致。

    2.4.2 多行注釋

    【建議】?避免使用?/*...*/?這樣的多行注釋。有多行注釋內容時,使用多個單行注釋。

    2.4.3 文檔化注釋

    【強制】?為了便于代碼閱讀和自文檔化,以下內容必須包含以?/**...*/?形式的塊注釋中。

    解釋:

  • 文件
  • namespace
  • 函數或方法
  • 類屬性
  • 事件
  • 全局變量
  • 常量
  • 【強制】?文檔注釋前必須空一行。
    【建議】?自文檔化的文檔說明 what,而不是 how。

    2.4.4 類型定義

    【強制】?類型定義都是以{開始, 以}結束。

    解釋:

    常用類型如:{string}, {number}, {boolean}, {Object}, {Function}, {RegExp}, {Array}, {Date}。

    類型不僅局限于內置的類型,也可以是自定義的類型。比如定義了一個類 Developer,就可以使用它來定義一個參數和返回值的類型。

    【強制】?對于基本類型 {string}, {number}, {boolean},首字母必須小寫。

    類型定義

    語法示例

    解釋

    String

    {string}

    --

    Number

    {number}

    --

    Boolean

    {boolean}

    --

    Object

    {Object}

    --

    Function

    {Function}

    --

    RegExp

    {RegExp}

    --

    Array

    {Array}

    --

    Date

    {Date}

    --

    單一類型集合

    {Array.<string>}

    string 類型的數組

    多類型

    {(number|boolean)}

    可能是 number 類型, 也可能是 boolean 類型

    允許為null

    {?number}

    可能是 number, 也可能是 null

    不允許為null

    {!Object}

    Object 類型, 但不是 null

    Function類型

    {function(number, boolean)}

    函數, 形參類型

    Function帶返回值

    {function(number, boolean):string}

    函數, 形參, 返回值類型

    參數可選

    @param {string=} name

    可選參數, =為類型后綴

    可變參數

    @param {...number} args

    變長參數, ...為類型前綴

    任意類型

    {*}

    任意類型

    可選任意類型

    @param {*=} name

    可選參數,類型不限

    可變任意類型

    @param {...*} args

    變長參數,類型不限

    2.4.5 文件注釋

    【強制】?文件頂部必須包含文件注釋,用?@file?標識文件說明。

    示例:

    /** * @file Describe the file */
    【建議】?文件注釋中可以用?@author?標識開發者信息。

    解釋:

    開發者信息能夠體現開發人員對文件的貢獻,并且能夠讓遇到問題或希望了解相關信息的人找到維護人。通常情況文件在被創建時標識的是創建者。隨著項目的進展,越來越多的人加入,參與這個文件的開發,新的作者應該被加入?@author?標識。

    @author?標識具有多人時,原則是按照?責任?進行排序。通常的說就是如果有問題,就是找第一個人應該比找第二個人有效。比如文件的創建者由于各種原因,模塊移交給了其他人或其他團隊,后來因為新增需求,其他人在新增代碼時,添加?@author標識應該把自己的名字添加在創建人的前面。

    @author?中的名字不允許被刪除。任何勞動成果都應該被尊重。

    業務項目中,一個文件可能被多人頻繁修改,并且每個人的維護時間都可能不會很長,不建議為文件增加?@author?標識。通過版本控制系統追蹤變更,按業務邏輯單元確定模塊的維護責任人,通過文檔與wiki跟蹤和查詢,是更好的責任管理方式。

    對于業務邏輯無關的技術型基礎項目,特別是開源的公共項目,應使用?@author?標識。

    示例:

    /** * @file Describe the file * @author author-name(mail-name@domain.com) *???????? author-name2(mail-name2@domain.com) */

    2.4.6 命名空間注釋

    【建議】?命名空間使用?@namespace?標識。

    示例:

    /** * @namespace */ var util = {};

    2.4.7 類注釋

    【建議】?使用?@class?標記類或構造函數。

    解釋:

    對于使用對象?constructor?屬性來定義的構造函數,可以使用?@constructor?來標記。

    示例:

    /** * 描述 * * @class */ function Developer() { ??? // constructor body }
    【建議】?使用?@extends?標記類的繼承信息。

    示例:

    /** * 描述 * * @class * @extends Developer */ function Fronteer() { ??? Developer.call(this); ??? // constructor body } util.inherits(Fronteer, Developer);
    【強制】?使用包裝方式擴展類成員時, 必須通過?@lends?進行重新指向。

    解釋:

    沒有?@lends?標記將無法為該類生成包含擴展類成員的文檔。

    示例:

    /** * 類描述 * * @class * @extends Developer */ function Fronteer() { ??? Developer.call(this); ??? // constructor body } ? util.extend( ??? Fronteer.prototype, ??? /** @lends Fronteer.prototype */{ ??????? _getLevel: function () { ??????????? // TODO ??????? } ??? } );
    【強制】?類的屬性或方法等成員信息使用?@public?/?@protected?/?@private?中的任意一個,指明可訪問性。

    解釋:

    生成的文檔中將有可訪問性的標記,避免用戶直接使用非?public?的屬性或方法。

    示例:

    /** * 類描述 * * @class * @extends Developer */ var Fronteer = function () { ??? Developer.call(this); ? ??? /** ???? * 屬性描述 ???? * ???? * @type {string} ???? * @private ???? */ ??? this._level = 'T12'; ? ??? // constructor body }; util.inherits(Fronteer, Developer); ? /** * 方法描述 * * @private * @return {string} 返回值描述 */ Fronteer.prototype._getLevel = function () { };

    2.4.8 函數/方法注釋

    【強制】?函數/方法注釋必須包含函數說明,有參數和返回值時必須使用注釋標識。
    【強制】?參數和返回值注釋必須包含類型信息和說明。
    【建議】?當函數是內部函數,外部不可訪問時,可以使用?@inner?標識。

    示例:

    /** * 函數描述 * * @param {string} p1 參數1的說明 * @param {string} p2 參數2的說明,比較長 *???? 那就換行了. * @param {number=} p3 參數3的說明(可選) * @return {Object} 返回值描述 */ function foo(p1, p2, p3) { ??? var p3 = p3 || 10; ??? return { ??????? p1: p1, ??????? p2: p2, ??????? p3: p3 ??? }; }
    【強制】?對 Object 中各項的描述, 必須使用?@param?標識。

    示例:

    /** * 函數描述 * * @param {Object} option 參數描述 * @param {string} option.url option項描述 * @param {string=} option.method option項描述,可選參數 */ function foo(option) { ??? // TODO }
    【建議】?重寫父類方法時, 應當添加?@override?標識。如果重寫的形參個數、類型、順序和返回值類型均未發生變化,可省略@param、@return,僅用?@override?標識,否則仍應作完整注釋。

    解釋:

    簡而言之,當子類重寫的方法能直接套用父類的方法注釋時可省略對參數與返回值的注釋。

    2.4.9 事件注釋

    【強制】?必須使用?@event?標識事件,事件參數的標識與方法描述的參數標識相同。

    示例:

    /** * 值變更時觸發 * * @event * @param {Object} e e描述 * @param {string} e.before before描述 * @param {string} e.after after描述 */ onchange: function (e) { }
    【強制】?在會廣播事件的函數前使用?@fires?標識廣播的事件,在廣播事件代碼前使用?@event?標識事件。
    【建議】?對于事件對象的注釋,使用?@param?標識,生成文檔時可讀性更好。

    示例:

    /** * 點擊處理 * * @fires Select#change * @private */ Select.prototype.clickHandler = function () { ??? /** ???? * 值變更時觸發 ???? * ???? * @event Select#change ???? * @param {Object} e e描述 ???? * @param {string} e.before before描述 ???? * @param {string} e.after after描述 ???? */ ??? this.fire( ??????? 'change', ??????? { ??????????? before: 'foo', ??????????? after: 'bar' ??????? } ??? ); };

    2.4.10 常量注釋

    【強制】?常量必須使用?@const?標記,并包含說明和類型信息。

    示例:

    /** * 常量說明 * * @const * @type {string} */ var REQUEST_URL = 'myurl.do';

    2.4.11 復雜類型注釋

    【建議】?對于類型未定義的復雜結構的注釋,可以使用?@typedef?標識來定義。

    示例:

    // `namespaceA~` 可以換成其它 namepaths 前綴,目的是為了生成文檔中能顯示 `@typedef` 定義的類型和鏈接。 /** * 服務器 * * @typedef {Object} namespaceA~Server * @property {string} host 主機 * @property {number} port 端口 */ ? /** * 服務器列表 * * @type {Array.<namespaceA~Server>} */ var servers = [ ??? { ??????? host: '1.2.3.4', ??????? port: 8080 ??? }, ??? { ??????? host: '1.2.3.5', ??????? port: 8081 ??? } ];

    2.4.12 細節注釋

    對于內部實現、不容易理解的邏輯說明、摘要信息等,我們可能需要編寫細節注釋。

    【建議】?細節注釋遵循單行注釋的格式。說明必須換行時,每行是一個單行注釋的起始。

    示例:

    function foo(p1, p2) { ??? // 這里對具體內部邏輯進行說明 ??? // 說明太長需要換行 ??? for (...) { ??????? .... ??? } }
    【強制】?有時我們會使用一些特殊標記進行說明。特殊標記必須使用單行注釋的形式。下面列舉了一些常用標記:

    解釋:

  • TODO: 有功能待實現。此時需要對將要實現的功能進行簡單說明。
  • FIXME: 該處代碼運行沒問題,但可能由于時間趕或者其他原因,需要修正。此時需要對如何修正進行簡單說明。
  • HACK: 為修正某些問題而寫的不太好或者使用了某些詭異手段的代碼。此時需要對思路或詭異手段進行描述。
  • XXX: 該處存在陷阱。此時需要對陷阱進行描述。
  • 3 語言特性

    3.1 變量

    【強制】?變量在使用前必須通過?var?定義。

    解釋:

    不通過 var 定義變量將導致變量污染全局環境。

    示例:

    // good var name = 'MyName'; ? // bad name = 'MyName';
    【強制】?每個?var?只能聲明一個變量。

    解釋:

    一個 var 聲明多個變量,容易導致較長的行長度,并且在修改時容易造成逗號和分號的混淆。

    示例:

    // good var hangModules = []; var missModules = []; var visited = {}; ? // bad var hangModules = [], ??? missModules = [], ??? visited = {};
    【強制】?變量必須?即用即聲明,不得在函數或其它形式的代碼塊起始位置統一聲明所有變量。

    解釋:

    變量聲明與使用的距離越遠,出現的跨度越大,代碼的閱讀與維護成本越高。雖然JavaScript的變量是函數作用域,還是應該根據編程中的意圖,縮小變量出現的距離空間。

    示例:

    // good function kv2List(source) { ??? var list = []; ? ??? for (var key in source) { ??????? if (source.hasOwnProperty(key)) { ??????????? var item = { ??????????????? k: key, ??????????????? v: source[key] ??????????? }; ??????????? list.push(item); ??????? } ??? } ? ??? return list; } ? // bad function kv2List(source) { ??? var list = []; ??? var key; ??? var item; ? ??? for (key in source) { ??????? if (source.hasOwnProperty(key)) { ??????????? item = { ??????????????? k: key, ??????????????? v: source[key] ??????????? }; ??????????? list.push(item); ??????? } ??? } ? ??? return list; }

    3.2 條件

    【強制】?在 Equality Expression 中使用類型嚴格的?===。僅當判斷 null 或 undefined 時,允許使用?== null。

    解釋:

    使用 === 可以避免等于判斷中隱式的類型轉換。

    示例:

    // good if (age === 30) { ??? // ...... } ? // bad if (age == 30) { ??? // ...... }
    【建議】?盡可能使用簡潔的表達式。

    示例:

    // 字符串為空 ? // good if (!name) { ??? // ...... } ? // bad if (name === '') { ??? // ...... } // 字符串非空 ? // good if (name) { ??? // ...... } ? // bad if (name !== '') { ??? // ...... } // 數組非空 ? // good if (collection.length) { ??? // ...... } ? // bad if (collection.length > 0) { ??? // ...... } // 布爾不成立 ? // good if (!notTrue) { ??? // ...... } ? // bad if (notTrue === false) { ??? // ...... } // null 或 undefined ? // good if (noValue == null) { ? // ...... } ? // bad if (noValue === null || typeof noValue === 'undefined') { ? // ...... }
    【建議】?按執行頻率排列分支的順序。

    解釋:

    按執行頻率排列分支的順序好處是:

  • 閱讀的人容易找到最常見的情況,增加可讀性。
  • 提高執行效率。
  • 【建議】?對于相同變量或表達式的多值條件,用?switch?代替?if。

    示例:

    // good switch (typeof variable) { ??? case 'object': ??????? // ...... ??????? break; ??? case 'number': ??? case 'boolean': ??? case 'string': ??????? // ...... ??????? break; } ? // bad var type = typeof variable; if (type === 'object') { ??? // ...... } else if (type === 'number' || type === 'boolean' || type === 'string') { ??? // ...... }
    【建議】?如果函數或全局中的?else?塊后沒有任何語句,可以刪除?else。

    示例:

    // good function getName() { ??? if (name) { ??????? return name; ??? } ? ??? return 'unnamed'; } ? // bad function getName() { ??? if (name) { ??????? return name; ??? } ??? else { ??????? return 'unnamed'; ??? } }

    3.3 循環

    【建議】?不要在循環體中包含函數表達式,事先將函數提取到循環體外。

    解釋:

    循環體中的函數表達式,運行過程中會生成循環次數個函數對象。

    示例:

    // good function clicker() { ??? // ...... } ? for (var i = 0, len = elements.length; i < len; i++) { ??? var element = elements[i]; ??? addListener(element, 'click', clicker); } ? ? // bad for (var i = 0, len = elements.length; i < len; i++) { ??? var element = elements[i]; ??? addListener(element, 'click', function () {}); }
    【建議】?對循環內多次使用的不變值,在循環外用變量緩存。

    示例:

    // good var width = wrap.offsetWidth + 'px'; for (var i = 0, len = elements.length; i < len; i++) { ??? var element = elements[i]; ??? element.style.width = width; ??? // ...... } ? ? // bad for (var i = 0, len = elements.length; i < len; i++) { ??? var element = elements[i]; ??? element.style.width = wrap.offsetWidth + 'px'; ??? // ...... }
    【建議】?對有序集合進行遍歷時,緩存?length。

    解釋:

    雖然現代瀏覽器都對數組長度進行了緩存,但對于一些宿主對象和老舊瀏覽器的數組對象,在每次 length 訪問時會動態計算元素個數,此時緩存 length 能有效提高程序性能。

    示例:

    for (var i = 0, len = elements.length; i < len; i++) { ??? var element = elements[i]; ??? // ...... }
    【建議】?對有序集合進行順序無關的遍歷時,使用逆序遍歷。

    解釋:

    逆序遍歷可以節省變量,代碼比較優化。

    示例:

    var len = elements.length; while (len--) { ??? var element = elements[len]; ??? // ...... }

    3.4 類型

    3.4.1 類型檢測

    【建議】?類型檢測優先使用?typeof。對象類型檢測使用?instanceof。null?或?undefined?的檢測使用?== null。

    示例:

    // string typeof variable === 'string' ? // number typeof variable === 'number' ? // boolean typeof variable === 'boolean' ? // Function typeof variable === 'function' ? // Object typeof variable === 'object' ? // RegExp variable instanceof RegExp ? // Array variable instanceof Array ? // null variable === null ? // null or undefined variable == null ? // undefined typeof variable === 'undefined'

    3.4.2 類型轉換

    【建議】?轉換成?string?時,使用?+ ''。

    示例:

    // good num + ''; ? // bad new String(num); num.toString(); String(num);
    【建議】?轉換成?number?時,通常使用?+。

    示例:

    // good +str; ? // bad Number(str);
    【建議】?string?轉換成?number,要轉換的字符串結尾包含非數字并期望忽略時,使用?parseInt。

    示例:

    var width = '200px'; parseInt(width, 10);
    【強制】?使用?parseInt?時,必須指定進制。

    示例:

    // good parseInt(str, 10); ? // bad parseInt(str);
    【建議】?轉換成?boolean?時,使用?!!。

    示例:

    var num = 3.14; !!num;
    【建議】?number?去除小數點,使用?Math.floor / Math.round / Math.ceil,不使用?parseInt。

    示例:

    // good var num = 3.14; Math.ceil(num); ? // bad var num = 3.14; parseInt(num, 10);

    3.5 字符串

    【強制】?字符串開頭和結束使用單引號?'。

    解釋:

  • 輸入單引號不需要按住 shift,方便輸入。
  • 實際使用中,字符串經常用來拼接 HTML。為方便 HTML 中包含雙引號而不需要轉義寫法。
  • 示例:

    var str = '我是一個字符串'; var html = '<div class="cls">拼接HTML可以省去雙引號轉義</div>';
    【建議】?使用?數組?或?+?拼接字符串。

    解釋:

  • 使用 + 拼接字符串,如果拼接的全部是 StringLiteral,壓縮工具可以對其進行自動合并的優化。所以,靜態字符串建議使用 + 拼接。
  • 在現代瀏覽器下,使用 + 拼接字符串,性能較數組的方式要高。
  • 如需要兼顧老舊瀏覽器,應盡量使用數組拼接字符串。
  • 示例:

    // 使用數組拼接字符串 var str = [ ??? // 推薦換行開始并縮進開始第一個字符串, 對齊代碼, 方便閱讀. ??? '<ul>', ??????? '<li>第一項</li>', ??????? '<li>第二項</li>', ??? '</ul>' ].join(''); ? // 使用 + 拼接字符串 var str2 = '' // 建議第一個為空字符串, 第二個換行開始并縮進開始, 對齊代碼, 方便閱讀 ??? + '<ul>', ??? +??? '<li>第一項</li>', ??? +??? '<li>第二項</li>', ??? + '</ul>';
    【建議】?復雜的數據到視圖字符串的轉換過程,選用一種模板引擎。

    解釋:

    使用模板引擎有如下好處:

  • 在開發過程中專注于數據,將視圖生成的過程由另外一個層級維護,使程序邏輯結構更清晰。
  • 優秀的模板引擎,通過模板編譯技術和高質量的編譯產物,能獲得比手工拼接字符串更高的性能。
    • artTemplate: 體積較小,在所有環境下性能高,語法靈活。
    • dot.js: 體積小,在現代瀏覽器下性能高,語法靈活。
    • etpl: 體積較小,在所有環境下性能高,模板復用性高,語法靈活。
    • handlebars: 體積大,在所有環境下性能高,擴展性高。
    • hogon: 體積小,在現代瀏覽器下性能高。
    • nunjucks: 體積較大,性能一般,模板復用性高。

    3.6 對象

    【強制】?使用對象字面量?{}?創建新?Object。

    示例:

    // good var obj = {}; ? // bad var obj = new Object();
    【強制】?對象創建時,如果一個對象的所有?屬性?均可以不添加引號,則所有?屬性?不得添加引號。

    示例:

    var info = { ??? name: 'someone', ??? age: 28 };
    【強制】?對象創建時,如果任何一個?屬性?需要添加引號,則所有?屬性?必須添加?'。

    解釋:

    如果屬性不符合 Identifier 和 NumberLiteral 的形式,就需要以 StringLiteral 的形式提供。

    示例:

    // good var info = { ??? 'name': 'someone', ??? 'age': 28, ??? 'more-info': '...' }; ? // bad var info = { ??? name: 'someone', ??? age: 28, ??? 'more-info': '...' };
    【強制】?不允許修改和擴展任何原生對象和宿主對象的原型。

    示例:

    // 以下行為絕對禁止 String.prototype.trim = function () { };
    【建議】?屬性訪問時,盡量使用?.。

    解釋:

    屬性名符合 Identifier 的要求,就可以通過?.?來訪問,否則就只能通過?[expr]?方式訪問。

    通常在 JavaScript 中聲明的對象,屬性命名是使用 Camel 命名法,用?.?來訪問更清晰簡潔。部分特殊的屬性(比如來自后端的JSON),可能采用不尋常的命名方式,可以通過?[expr]?方式訪問。

    示例:

    info.age; info['more-info'];
    【建議】?for in?遍歷對象時, 使用?hasOwnProperty?過濾掉原型中的屬性。

    示例:

    var newInfo = {}; for (var key in info) { ??? if (info.hasOwnProperty(key)) { ??????? newInfo[key] = info[key]; ??? } }

    3.7 數組

    【強制】?使用數組字面量?[]?創建新數組,除非想要創建的是指定長度的數組。

    示例:

    // good var arr = []; ? // bad var arr = new Array();
    【強制】?遍歷數組不使用?for in。

    解釋:

    數組對象可能存在數字以外的屬性, 這種情況下 for in 不會得到正確結果.

    示例:

    var arr = ['a', 'b', 'c']; arr.other = 'other things'; // 這里僅作演示, 實際中應使用Object類型 ? // 正確的遍歷方式 for (var i = 0, len = arr.length; i < len; i++) { ??? console.log(i); } ? // 錯誤的遍歷方式 for (i in arr) { ??? console.log(i); }
    【建議】?不因為性能的原因自己實現數組排序功能,盡量使用數組的?sort?方法。

    解釋:

    自己實現的常規排序算法,在性能上并不優于數組默認的 sort 方法。以下兩種場景可以自己實現排序:

  • 需要穩定的排序算法,達到嚴格一致的排序結果。
  • 數據特點鮮明,適合使用桶排。
  • 【建議】?清空數組使用?.length = 0。

    3.8 函數

    3.8.1 函數長度

    【建議】?一個函數的長度控制在?50?行以內。

    解釋:

    將過多的邏輯單元混在一個大函數中,易導致難以維護。一個清晰易懂的函數應該完成單一的邏輯單元。復雜的操作應進一步抽取,通過函數的調用來體現流程。

    特定算法等不可分割的邏輯允許例外。

    示例:

    function syncViewStateOnUserAction() { ??? if (x.checked) { ??????? y.checked = true; ??????? z.value = ''; ??? } ??? else { ??????? y.checked = false; ??? } ? ??? if (!a.value) { ??????? warning.innerText = 'Please enter it'; ??????? submitButton.disabled = true; ??? } ??? else { ??????? warning.innerText = ''; ??????? submitButton.disabled = false; ??? } } ? // 直接閱讀該函數會難以明確其主線邏輯,因此下方是一種更合理的表達方式: ? function syncViewStateOnUserAction() { ??? syncXStateToView(); ??? checkAAvailability(); } ? function syncXStateToView() { ??? if (x.checked) { ??????? y.checked = true; ??????? z.value = ''; ??? } ??? else { ??????? y.checked = false; ??? } } ? function checkAAvailability() { ??? if (!a.value) { ??????? displayWarningForAMissing(); ??? } ??? else { ??????? clearWarnignForA(); ??? } }

    3.8.2 參數設計

    【建議】?一個函數的參數控制在?6?個以內。

    解釋:

    除去不定長參數以外,函數具備不同邏輯意義的參數建議控制在 6 個以內,過多參數會導致維護難度增大。

    【建議】?通過?options?參數傳遞非數據輸入型參數。

    解釋:

    有些函數的參數并不是作為算法的輸入,而是對算法的某些分支條件判斷之用,此類參數建議通過一個 options 參數傳遞。

    如下函數:

    /** * 移除某個元素 * * @param {Node} element 需要移除的元素 * @param {boolean} removeEventListeners 是否同時將所有注冊在元素上的事件移除 */ function removeElement(element, removeEventListeners) { ??? element.parent.removeChild(element); ??? if (removeEventListeners) { ??????? element.clearEventListeners(); ??? } }

    可以轉換為下面的簽名:

    /** * 移除某個元素 * * @param {Node} element 需要移除的元素 * @param {Object} options 相關的邏輯配置 * @param {boolean} options.removeEventListeners 是否同時將所有注冊在元素上的事件移除 */ function removeElement(element, options) { ??? element.parent.removeChild(element); ??? if (options.removeEventListeners) { ??????? element.clearEventListeners(); ??? } }

    這種模式有幾個顯著的優勢:

    • boolean 型的配置項具備名稱,從調用的代碼上更易理解其表達的邏輯意義。
    • 當配置項有增長時,無需無休止地增加參數個數,不會出現 removeElement(element, true, false, false, 3) 這樣難以理解的調用代碼。
    • 當部分配置參數可選時,多個參數的形式非常難處理重載邏輯,而使用一個 options 對象只需判斷屬性是否存在,實現得以簡化。

    3.8.3 閉包

    【建議】?在適當的時候將閉包內大對象置為?null。

    解釋:

    在 JavaScript 中,無需特別的關鍵詞就可以使用閉包,一個函數可以任意訪問在其定義的作用域外的變量。需要注意的是,函數的作用域是靜態的,即在定義時決定,與調用的時機和方式沒有任何關系。

    閉包會阻止一些變量的垃圾回收,對于較老舊的JavaScript引擎,可能導致外部所有變量均無法回收。

    首先一個較為明確的結論是,以下內容會影響到閉包內變量的回收:

    • 嵌套的函數中是否有使用該變量。
    • 嵌套的函數中是否有?直接調用eval
    • 是否使用了 with 表達式。

    Chakra、V8 和 SpiderMonkey 將受以上因素的影響,表現出不盡相同又較為相似的回收策略,而JScript.dll和Carakan則完全沒有這方面的優化,會完整保留整個 LexicalEnvironment 中的所有變量綁定,造成一定的內存消耗。

    由于對閉包內變量有回收優化策略的 Chakra、V8 和 SpiderMonkey 引擎的行為較為相似,因此可以總結如下,當返回一個函數 fn 時:

  • 如果 fn 的 [[Scope]] 是ObjectEnvironment(with 表達式生成 ObjectEnvironment,函數和 catch 表達式生成 DeclarativeEnvironment),則:
  • 如果是 V8 引擎,則退出全過程。
  • 如果是 SpiderMonkey,則處理該 ObjectEnvironment 的外層 LexicalEnvironment。
  • 獲取當前 LexicalEnvironment 下的所有類型為 Function 的對象,對于每一個 Function 對象,分析其 FunctionBody:
  • 如果 FunctionBody 中含有?直接調用eval,則退出全過程。
  • 否則得到所有的 Identifier。
  • 對于每一個 Identifier,設其為 name,根據查找變量引用的規則,從 LexicalEnvironment 中找出名稱為 name 的綁定 binding。
  • 對 binding 添加 notSwap 屬性,其值為 true。
  • 檢查當前 LexicalEnvironment 中的每一個變量綁定,如果該綁定有 notSwap 屬性且值為 true,則:
  • 如果是V8引擎,刪除該綁定。
  • 如果是SpiderMonkey,將該綁定的值設為 undefined,將刪除 notSwap 屬性。
  • 對于Chakra引擎,暫無法得知是按 V8 的模式還是按 SpiderMonkey 的模式進行。

    如果有?非常龐大?的對象,且預計會在?老舊的引擎?中執行,則使用閉包時,注意將閉包不需要的對象置為空引用。

    【建議】?使用?IIFE?避免?Lift 效應。

    解釋:

    在引用函數外部變量時,函數執行時外部變量的值由運行時決定而非定義時,最典型的場景如下:

    var tasks = []; for (var i = 0; i < 5; i++) { ??? tasks[tasks.length] = function () { ??????? console.log('Current cursor is at ' + i); ??? }; } ? var len = tasks.length; while (len--) { ??? tasks[len](); }

    以上代碼對 tasks 中的函數的執行均會輸出?Current cursor is at 5,往往不符合預期。

    此現象稱為?Lift 效應?。解決的方式是通過額外加上一層閉包函數,將需要的外部變量作為參數傳遞來解除變量的綁定關系:

    var tasks = []; for (var i = 0; i < 5; i++) { ??? // 注意有一層額外的閉包 ??? tasks[tasks.length] = (function (i) { ??????? return function () { ??????????? console.log('Current cursor is at ' + i); ??????? }; ??? })(i); } ? var len = tasks.length; while (len--) { ??? tasks[len](); }

    3.8.4 空函數

    【建議】?空函數不使用?new Function()?的形式。

    示例:

    var emptyFunction = function () {};
    【建議】?對于性能有高要求的場合,建議存在一個空函數的常量,供多處使用共享。

    示例:

    var EMPTY_FUNCTION = function () {}; ? function MyClass() { } ? MyClass.prototype.abstractMethod = EMPTY_FUNCTION; MyClass.prototype.hooks.before = EMPTY_FUNCTION; MyClass.prototype.hooks.after = EMPTY_FUNCTION;

    3.9 面向對象

    【強制】?類的繼承方案,實現時需要修正?constructor。

    解釋:

    通常使用其他 library 的類繼承方案都會進行 constructor 修正。如果是自己實現的類繼承方案,需要進行 constructor 修正。

    示例:

    /** * 構建類之間的繼承關系 * ?* @param {Function} subClass 子類函數 * @param {Function} superClass 父類函數 */ function inherits(subClass, superClass) { ??? var F = new Function(); ??? F.prototype = superClass.prototype; ??? subClass.prototype = new F(); ??? subClass.prototype.constructor = subClass; }
    【建議】?聲明類時,保證?constructor?的正確性。

    示例:

    function Animal(name) { ??? this.name = name; } ? // 直接prototype等于對象時,需要修正constructor Animal.prototype = { ??? constructor: Animal, ? ??? jump: function () { ??????? alert('animal ' + this.name + ' jump'); ??? } }; ? // 這種方式擴展prototype則無需理會constructor Animal.prototype.jump = function () { ??? alert('animal ' + this.name + ' jump'); };
    【建議】?屬性在構造函數中聲明,方法在原型中聲明。

    解釋:

    原型對象的成員被所有實例共享,能節約內存占用。所以編碼時我們應該遵守這樣的原則:原型對象包含程序不會修改的成員,如方法函數或配置項。

    function TextNode(value, engine) { ??? this.value = value; ??? this.engine = engine; } ? TextNode.prototype.clone = function () { ??? return this; };
    【強制】?自定義事件的?事件名?必須全小寫。

    解釋:

    在 JavaScript 廣泛應用的瀏覽器環境,絕大多數 DOM 事件名稱都是全小寫的。為了遵循大多數 JavaScript 開發者的習慣,在設計自定義事件時,事件名也應該全小寫。

    【強制】?自定義事件只能有一個?event?參數。如果事件需要傳遞較多信息,應仔細設計事件對象。

    解釋:

    一個事件對象的好處有:

  • 順序無關,避免事件監聽者需要記憶參數順序。
  • 每個事件信息都可以根據需要提供或者不提供,更自由。
  • 擴展方便,未來添加事件信息時,無需考慮會破壞監聽器參數形式而無法向后兼容。
  • 【建議】?設計自定義事件時,應考慮禁止默認行為。

    解釋:

    常見禁止默認行為的方式有兩種:

  • 事件監聽函數中 return false。
  • 事件對象中包含禁止默認行為的方法,如 preventDefault。
  • 3.10 動態特性

    3.10.1 eval

    【強制】?避免使用直接?eval?函數。

    解釋:

    直接 eval,指的是以函數方式調用 eval 的調用方法。直接 eval 調用執行代碼的作用域為本地作用域,應當避免。

    如果有特殊情況需要使用直接 eval,需在代碼中用詳細的注釋說明為何必須使用直接 eval,不能使用其它動態執行代碼的方式,同時需要其他資深工程師進行 Code Review。

    【建議】?盡量避免使用?eval?函數。

    3.10.2 動態執行代碼

    【建議】?使用?new Function?執行動態代碼。

    解釋:

    通過 new Function 生成的函數作用域是全局使用域,不會影響當當前的本地作用域。如果有動態代碼執行的需求,建議使用 new Function。

    示例:

    var handler = new Function('x', 'y', 'return x + y;'); var result = handler($('#x').val(), $('#y').val());

    3.10.3 with

    【建議】?盡量不要使用?with。

    解釋:

    使用 with 可能會增加代碼的復雜度,不利于閱讀和管理;也會對性能有影響。大多數使用 with 的場景都能使用其他方式較好的替代。所以,盡量不要使用 with。

    3.10.4 delete

    【建議】?減少?delete?的使用。

    解釋:

    如果沒有特別的需求,減少或避免使用delete。delete的使用會破壞部分 JavaScript 引擎的性能優化。

    【建議】?處理?delete?可能產生的異常。

    解釋:

    對于有被遍歷需求,且值 null 被認為具有業務邏輯意義的值的對象,移除某個屬性必須使用 delete 操作。

    在嚴格模式或IE下使用 delete 時,不能被刪除的屬性會拋出異常,因此在不確定屬性是否可以刪除的情況下,建議添加 try-catch 塊。

    示例:

    try { ??? delete o.x; } catch (deleteError) { ??? o.x = null; }

    3.10.5 對象屬性

    【建議】?避免修改外部傳入的對象。

    解釋:

    JavaScript 因其腳本語言的動態特性,當一個對象未被 seal 或 freeze 時,可以任意添加、刪除、修改屬性值。

    但是隨意地對 非自身控制的對象 進行修改,很容易造成代碼在不可預知的情況下出現問題。因此,設計良好的組件、函數應該避免對外部傳入的對象的修改。

    下面代碼的 selectNode 方法修改了由外部傳入的 datasource 對象。如果 datasource 用在其它場合(如另一個 Tree 實例)下,會造成狀態的混亂。

    function Tree(datasource) { ??? this.datasource = datasource; } ? Tree.prototype.selectNode = function (id) { ??? // 從datasource中找出節點對象 ??? var node = this.findNode(id); ??? if (node) { ??????? node.selected = true; ??????? this.flushView(); ??? } };

    對于此類場景,需要使用額外的對象來維護,使用由自身控制,不與外部產生任何交互的 selectedNodeIndex 對象來維護節點的選中狀態,不對 datasource 作任何修改。

    function Tree(datasource) { ??? this.datasource = datasource; ??? this.selectedNodeIndex = {}; } ? Tree.prototype.selectNode = function (id) { ??? // 從datasource中找出節點對象 ??? var node = this.findNode(id); ??? if (node) { ??????? this.selectedNodeIndex[id] = true; ??????? this.flushView(); ??? } };

    除此之外,也可以通過 deepClone 等手段將自身維護的對象與外部傳入的分離,保證不會相互影響。

    【建議】?具備強類型的設計。

    解釋:

    • 如果一個屬性被設計為 boolean 類型,則不要使用 1 / 0 作為其值。對于標識性的屬性,如對代碼體積有嚴格要求,可以從一開始就設計為 number 類型且將 0 作為否定值。
    • 從 DOM 中取出的值通常為 string 類型,如果有對象或函數的接收類型為 number 類型,提前作好轉換,而不是期望對象、函數可以處理多類型的值。

    4 瀏覽器環境

    4.1 DOM

    4.1.1 元素獲取

    【建議】?對于單個元素,盡可能使用?document.getElementById?獲取,避免使用document.all。
    【建議】?對于多個元素的集合,盡可能使用?context.getElementsByTagName?獲取。其中?context?可以為?document?或其他元素。指定?tagName?參數為?*?可以獲得所有子元素。
    【建議】?遍歷元素集合時,盡量緩存集合長度。如需多次操作同一集合,則應將集合轉為數組。

    解釋:

    原生獲取元素集合的結果并不直接引用 DOM 元素,而是對索引進行讀取,所以 DOM 結構的改變會實時反映到結果中。

    示例:

    <div></div> <span></span> ? <script> var elements = document.getElementsByTagName('*'); ? // 顯示為 DIV alert(elements[0].tagName); ? var div = elements[0]; var p = document.createElement('p'); docpment.body.insertBefore(p, div); ? // 顯示為 P alert(elements[0].tagName); </script>
    【建議】?獲取元素的直接子元素時使用?children。避免使用childNodes,除非預期是需要包含文本、注釋和屬性類型的節點。

    4.1.2 樣式獲取

    【建議】?獲取元素實際樣式信息時,應使用?getComputedStyle?或?currentStyle。

    解釋:

    通過 style 只能獲得內聯定義或通過 JavaScript 直接設置的樣式。通過 CSS class 設置的元素樣式無法直接通過 style 獲取。

    4.1.3 樣式設置

    【建議】?盡可能通過為元素添加預定義的 className 來改變元素樣式,避免直接操作 style 設置。
    【強制】?通過 style 對象設置元素樣式時,對于帶單位非 0 值的屬性,不允許省略單位。

    解釋:

    除了 IE,標準瀏覽器會忽略不規范的屬性值,導致兼容性問題。

    4.1.4 DOM 操作

    【建議】?操作?DOM?時,盡量減少頁面?reflow。

    解釋:

    頁面 reflow 是非常耗時的行為,非常容易導致性能瓶頸。下面一些場景會觸發瀏覽器的reflow:

    • DOM元素的添加、修改(內容)、刪除。
    • 應用新的樣式或者修改任何影響元素布局的屬性。
    • Resize瀏覽器窗口、滾動頁面。
    • 讀取元素的某些屬性(offsetLeft、offsetTop、offsetHeight、offsetWidth、scrollTop/Left/Width/Height、clientTop/Left/Width/Height、getComputedStyle()、currentStyle(in IE)) 。
    【建議】?盡量減少?DOM?操作。

    解釋:

    DOM 操作也是非常耗時的一種操作,減少 DOM 操作有助于提高性能。舉一個簡單的例子,構建一個列表。我們可以用兩種方式:

  • 在循環體中 createElement 并 append 到父元素中。
  • 在循環體中拼接 HTML 字符串,循環結束后寫父元素的 innerHTML。
  • 第一種方法看起來比較標準,但是每次循環都會對 DOM 進行操作,性能極低。在這里推薦使用第二種方法。

    4.1.5 DOM 事件

    【建議】?優先使用?addEventListener / attachEvent?綁定事件,避免直接在 HTML 屬性中或 DOM 的?expando?屬性綁定事件處理。

    解釋:

    expando 屬性綁定事件容易導致互相覆蓋。

    【建議】?使用?addEventListener?時第三個參數使用?false。

    解釋:

    標準瀏覽器中的 addEventListener 可以通過第三個參數指定兩種時間觸發模型:冒泡和捕獲。而 IE 的 attachEvent 僅支持冒泡的事件觸發。所以為了保持一致性,通常 addEventListener 的第三個參數都為 false。

    【建議】?在沒有事件自動管理的框架支持下,應持有監聽器函數的引用,在適當時候(元素釋放、頁面卸載等)移除添加的監聽器。

    ?

    轉載于:https://www.cnblogs.com/z-e-r-o/p/6726855.html

    總結

    以上是生活随笔為你收集整理的前端开发规范文档(html,css,js)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    亚洲男女精品 | 99热这里有精品 | 狠狠色丁香婷婷综合久小说久 | 国产精品永久免费在线 | 精品女同一区二区三区在线观看 | 懂色av一区二区三区蜜臀 | 国产精品毛片完整版 | 欧美了一区在线观看 | 在线亚洲人成电影网站色www | 久草视频手机在线 | 久久久久久久免费 | 久久国产精彩视频 | 午夜999 | 成人一级| 免费看片网址 | 免费看久久 | 波多野结衣视频在线 | 久久只精品99品免费久23小说 | 国产精品美女久久久网av | 国产视频一区在线 | 超碰在线人人爱 | 青青河边草免费观看 | 国产黄色片久久久 | 亚洲欧美国产日韩在线观看 | 久热只有精品 | 国产香蕉久久 | 亚洲影院国产 | 午夜视频在线观看欧美 | 99久精品 | 日韩,精品电影 | 91色吧 | 色噜噜在线观看视频 | 精品一区二区三区四区在线 | 丁香五月网久久综合 | 亚洲黄色一级视频 | 丁香国产视频 | 亚洲精品视频在线观看视频 | 国产一卡二卡在线 | 最近中文字幕大全中文字幕免费 | 91免费观看视频在线 | 日韩视频免费观看高清完整版在线 | 成人av资源站 | 国产综合91 | 欧美天堂久久 | 亚洲国产日本 | 奇米影视在线99精品 | 国产成人精品午夜在线播放 | 国产精品麻 | 国产在线a| 欧美日产在线观看 | 超碰97免费在线 | 日韩在线影视 | 天天干天天搞天天射 | 狠狠干电影 | 一区免费视频 | 久久久麻豆精品一区二区 | 国产成人免费观看久久久 | 手机av永久免费 | 日本中文字幕网站 | 日本亚洲国产 | 亚洲综合视频在线观看 | 国产精品日韩高清 | 久草视频免费在线播放 | 亚洲精品美女在线观看播放 | 超碰免费97| 婷婷色站| 99爱在线观看 | 亚洲精品乱码久久久久久高潮 | 色婷婷www | 色婷婷久久久综合中文字幕 | 91丨九色丨高潮 | 天天色天天射天天综合网 | 国产91精品一区二区绿帽 | 色婷婷电影网 | 国产精品久久艹 | 久久久久免费精品视频 | 91mv.cool在线观看 | 99视频精品免费观看, | 国产精品亚洲片夜色在线 | 天天操夜夜操夜夜操 | 00av视频 | 美女黄频在线观看 | 奇米影视8888 | 丰满少妇对白在线偷拍 | 97超碰福利久久精品 | 久久久99精品免费观看 | 中文字幕 国产专区 | 久久综合狠狠 | 日日噜噜噜噜夜夜爽亚洲精品 | 在线免费中文字幕 | 亚洲国产成人高清精品 | 国产高清免费在线观看 | 亚洲黄色区 | 日韩精品一区二区在线视频 | 久久综合久久综合这里只有精品 | 国产综合精品一区二区三区 | 日韩一区二区三区在线看 | 免费看wwwwwwwwwww的视频 久久久久久99精品 91中文字幕视频 | 国产一级大片在线观看 | 24小时日本在线www免费的 | 欧美国产日韩一区二区三区 | 久久99国产综合精品免费 | 九九九九九九精品任你躁 | 久久天天躁狠狠躁亚洲综合公司 | 中文字幕在线免费观看 | 久久成人综合视频 | 欧美日韩中文视频 | 91九色蝌蚪视频 | 右手影院亚洲欧美 | 久草在线视频在线 | 日本一区二区三区免费看 | 欧美激情视频一二三区 | 99精品国产一区二区 | 不卡的av在线 | 黄色免费看片网站 | 亚洲综合色视频 | 日本一区二区三区免费观看 | bbw av| 激情开心站 | 国产精品久久久久久久久久ktv | 在线看黄色av | 欧美激情视频一二区 | 97精品国产97久久久久久粉红 | 91九色网站| 国产资源网 | 国产不卡在线看 | 日日爱av| 91精品在线免费视频 | 日本久久久久久久久久久 | 97国产人人| 在线成人免费电影 | 久久精品官网 | www.黄色片网站 | 午夜精品成人一区二区三区 | 九九热免费观看 | 欧美在线你懂的 | 天天操天天摸天天干 | 999精品网 | 中文超碰字幕 | 欧美一级久久 | 色综合久久久久 | 五月天中文字幕 | 久久精品欧美一 | 亚洲91av| www.五月婷婷 | 精品视频区| aaa日本高清在线播放免费观看 | 天天综合天天综合 | 日韩特级黄色片 | 亚洲精品高清在线 | 在线日韩一区 | 91香蕉视频在线下载 | 欧美成人在线网站 | 久久av电影 | 国产欧美日韩一区 | 久久精品1区2区 | 日韩av一区二区在线影视 | 最近中文字幕完整高清 | 最新av网站在线观看 | 国产一区二区影院 | 一区二区中文字幕在线播放 | 国产精品永久免费观看 | 黄色亚洲大片免费在线观看 | 国产免费视频一区二区裸体 | 奇米影视8888 | 伊人天堂久久 | 免费人做人爱www的视 | 国产精品久久久精品 | 在线91播放| 黄色亚洲大片免费在线观看 | 日日碰狠狠躁久久躁综合网 | 涩涩网站在线 | 国产精品在线看 | 最近中文字幕在线 | 成人黄色免费在线观看 | 成人影音在线 | 国产人成看黄久久久久久久久 | 日韩美女免费线视频 | 最新av中文字幕 | 99爱视频在线观看 | 国产精品久久久区三区天天噜 | www.狠狠色 | 国产成人99av超碰超爽 | 久久久久久久久免费视频 | 国产午夜精品av一区二区 | 午夜视频亚洲 | 国色天香永久免费 | 九九九国产 | 久久精品一区二区三区国产主播 | 国产精品久久久久永久免费观看 | 在线亚洲天堂网 | av电影中文字幕在线观看 | 98超碰在线观看 | 99精品在线视频观看 | 色婷婷综合久久久中文字幕 | 91久久在线观看 | 国产精品一区二区无线 | 日韩免费电影一区二区三区 | 丁香婷婷激情五月 | 日韩91在线 | 国产精品二区在线观看 | 色综合久久久久久中文网 | 婷婷www| 久久99久久精品国产 | 精品免费国产一区二区三区四区 | www.狠狠插.com| 日韩va亚洲va欧美va久久 | 久久视频国产精品免费视频在线 | 欧美日韩一区三区 | 91亚洲在线观看 | 国产精品一区二区三区免费看 | 六月婷色 | 国产一级电影网 | 成人永久在线 | 99免在线观看免费视频高清 | a在线免费 | 美女福利视频在线 | 成人黄色小说视频 | 国产精品va在线观看入 | 天天干天天操天天搞 | 天天综合导航 | 精品国产一区二区三区四区vr | 中文字幕亚洲欧美 | 天天操天天曰 | 欧美大香线蕉线伊人久久 | 521色香蕉网站在线观看 | 美女视频黄的免费的 | 国产高清在线免费观看 | 一级黄网| 一区二区视频在线看 | 亚洲经典视频在线观看 | 不卡国产在线 | 日韩中文字幕一区 | 成人精品久久久 | 一区二区三区国产欧美 | 欧美精品免费在线 | 香蕉97视频观看在线观看 | 日韩性网站| 天天综合网在线 | 国产精久久久 | 亚洲自拍自偷 | 国产麻豆精品免费视频 | 久久精品久久99 | 国产香蕉av | 日本中文字幕在线电影 | 日韩一区二区免费在线观看 | 国产手机视频在线观看 | 免费在线黄色av | 日韩电影在线观看一区二区 | 美女网站色免费 | 九九视频热 | 天天射综合网视频 | 国产亚洲永久域名 | 欧美日韩网站 | 探花视频在线版播放免费观看 | 97精品一区二区三区 | 91成人在线视频观看 | 日韩精品网址 | 九九热精品视频在线观看 | 亚洲激情| 操操日日 | 国产免费成人av | 日韩午夜电影院 | 国产精品露脸在线 | 色全色在线资源网 | 久久综合九色 | 中文字幕免费播放 | 成人黄色小说在线观看 | 91福利区一区二区三区 | 午夜精品一区二区三区四区 | 五月综合久久 | 久久国产精品视频免费看 | 天天干天天天 | 成人免费视频视频在线观看 免费 | avav99| 国产最顶级的黄色片在线免费观看 | 香蕉在线视频播放网站 | 国产裸体bbb视频 | 97超碰色偷偷 | 天天色天天干天天色 | 日韩av片在线 | 精品久久久亚洲 | 日韩高清av| 国内精品久久久久影院日本资源 | 97成人精品视频在线观看 | 中文字幕第一页在线 | 亚洲欧美国产日韩在线观看 | 久久精品久久精品久久39 | 日本色小说视频 | 九九视频这里只有精品 | 日本成人黄色片 | 国产精品一区久久久久 | 亚洲人精品午夜 | 国产精品一区二区三区免费看 | 免费网站观看www在线观看 | 国产69精品久久久久久 | 国产资源在线免费观看 | 中文字幕亚洲欧美日韩 | 91人人视频在线观看 | 中文字幕精品三级久久久 | 精品黄色片 | 色狠狠综合| 国产美女免费观看 | 在线小视频国产 | 三级在线国产 | 中文区中文字幕免费看 | 97视频在线免费观看 | 亚洲精品国产区 | 天天色天天干天天色 | 成年人免费在线观看 | 久草久热| 成人免费xxxxxx视频 | 在线看免费 | 在线中文字幕播放 | 六月天综合网 | 在线观看av黄色 | 久久人91精品久久久久久不卡 | 久久免费成人 | 97视频一区| 在线免费观看黄色 | 午夜色大片在线观看 | 精品在线视频观看 | 欧美日在线观看 | 成人影片在线播放 | 日本最新中文字幕 | 日韩欧美久久 | 操少妇视频 | 天天激情站 | 丁香婷婷久久久综合精品国产 | 日本 在线 视频 中文 有码 | 欧美日韩3p | 天天躁日日躁狠狠躁 | 久久在线免费观看视频 | 91最新中文字幕 | 国内精品美女在线观看 | 天天艹日日干 | 蜜臀av性久久久久蜜臀aⅴ流畅 | 午夜精品久久久久久久99水蜜桃 | 日韩,中文字幕 | 国产一区视频在线 | 国产视频 亚洲精品 | 亚洲精品tv | 久久精品国产精品 | 国产va饥渴难耐女保洁员在线观看 | 91最新网址| 久久最新 | 99久久99久久精品免费 | 免费日韩av电影 | 免费观看av网站 | 国产裸体永久免费视频网站 | 久久精精品视频 | 最新亚洲视频 | 91爱在线| 特级毛片网站 | 91成人精品观看 | 免费黄色网址大全 | 天天碰天天操视频 | 日韩av在线网站 | 国产精品嫩草影院99网站 | 日韩精品欧美视频 | 色综合久久88 | 日韩精品综合在线 | 蜜臀av性久久久久av蜜臀三区 | 久久久精品免费看 | 狠狠狠色丁香综合久久天下网 | 国产视频精品久久 | 成人黄色电影视频 | a成人v | 亚洲黄色小说网 | 91精品国产成人观看 | 天堂av在线7 | 911久久香蕉国产线看观看 | 亚洲乱码在线 | 日韩午夜在线 | 国产精品久久久久aaaa | 日韩欧美视频在线免费观看 | 狠狠操狠狠干2017 | 超碰官网 | 日本久久久久久科技有限公司 | 国产va在线 | 伊人激情网 | 国产成人精品在线观看 | 天天草天天插 | 国产1级毛片 | 久久亚洲国产精品 | 欧美国产日韩一区二区 | 91精品国产91久久久久福利 | 超碰在线人人爱 | 国产99中文字幕 | 美女网站在线观看 | 蜜臀一区二区三区精品免费视频 | 91视频麻豆视频 | 人人爽人人爽人人爽人人爽 | 成年人三级网站 | 天天干人人插 | 视频在线观看91 | 91成人短视频在线观看 | 久久久久国产成人精品亚洲午夜 | 91亚洲精品久久久 | 91人人射 | 中文av在线天堂 | 免费久久久 | 国产综合在线视频 | 丁香花在线视频观看免费 | 麻豆果冻剧传媒在线播放 | av在线播放一区二区三区 | 97人人射 | 国产精品永久在线 | 亚洲欧洲国产精品 | 激情五月亚洲 | 黄色毛片视频 | av夜夜操 | 天天操天天操天天 | 久久精品视频网站 | 久久精彩 | 精品一区二区三区香蕉蜜桃 | 手机在线观看国产精品 | 久久er99热精品一区二区三区 | 亚洲精品国产精品国自产观看 | 97在线观看免费观看高清 | 国产黄色片免费在线观看 | 天天av综合网 | 国产成人精品免高潮在线观看 | 久久久久国产一区二区三区四区 | 狠狠色丁香婷婷综合久久片 | 欧洲精品视频一区二区 | 欧美日韩精品二区第二页 | 成人免费在线视频 | 国产精品一区二区久久精品爱涩 | 久久不卡av | 亚洲午夜久久久久久久久久久 | 色噜噜噜 | 欧美91精品国产自产 | 亚洲jizzjizz日本少妇 | 日本久久久亚洲精品 | 国产91丝袜在线播放动漫 | 91精品福利在线 | 狠狠狠狠狠狠天天爱 | 国产一区二区三区网站 | 最新影院 | 免费观看一级视频 | 国产剧情在线一区 | 中文字幕免费观看全部电影 | 日韩网站在线看片你懂的 | 91毛片在线观看 | 国产主播大尺度精品福利免费 | 久久国产影院 | 又色又爽又激情的59视频 | 日本性动态图 | 中文字幕 欧美性 | 狠狠狠色丁香婷婷综合久久88 | 国产婷婷久久 | 国产精品黄 | 97国产在线播放 | 中文字幕 国产精品 | 成人在线一区二区三区 | 国产又粗又长又硬免费视频 | 日韩精品电影在线播放 | 国产成人av在线 | 天天射综合网站 | 婷婷色吧| 国产伦理久久精品久久久久_ | 亚洲免费激情 | 国产精品久久久久久久久免费看 | 免费黄av | 国产一及片 | 亚洲综合在线发布 | 免费在线a | 久久久国产一区二区三区四区小说 | 在线99| 久久免费观看视频 | 国产成人黄色片 | 最近中文字幕国语免费高清6 | 成人免费观看完整版电影 | 国产在线观看h | 丁香五香天综合情 | 亚洲 欧美日韩 国产 中文 | 国产人成一区二区三区影院 | 草莓视频在线观看免费观看 | 国产亚洲精品久久久久久久久久 | 黄色av网站在线免费观看 | 日韩在线一区二区免费 | 国产一区二区在线观看视频 | 天天爽人人爽夜夜爽 | 欧美成人h版在线观看 | 日韩大片在线免费观看 | 麻豆国产电影 | 99国产精品一区 | 超碰人人做 | 精品欧美一区二区三区久久久 | 中文字幕免费国产精品 | 久久96国产精品久久99漫画 | 国产精品aⅴ | 国产成人精品一区二区三区网站观看 | 久久激情视频 久久 | 亚洲 中文 在线 精品 | 久久综合加勒比 | 国产馆在线播放 | 欧美最猛性xxxxx免费 | 嫩草伊人久久精品少妇av | 视频在线日韩 | av大片免费 | 国产成人福利在线观看 | 天天插狠狠干 | 九九九在线观看视频 | 黄色成年片 | 人人揉人人揉人人揉人人揉97 | 亚洲成人av片 | 999国产精品视频 | 国产一级久久 | 国产精品 国内视频 | 操高跟美女 | 综合色狠狠 | 99热9| 麻豆影视在线播放 | 五月婷婷操| 美女视频黄色免费 | 天天草天天插 | 日韩最新在线视频 | 中文字幕人成不卡一区 | 97福利社| 四虎影视国产精品免费久久 | 91久久精品日日躁夜夜躁国产 | 夜夜夜影院 | 国产亚洲精品福利 | 92中文资源在线 | 97视频久久久| 狠狠狠干狠狠 | 精品一区中文字幕 | 欧美精品国产综合久久 | 国产成a人亚洲精v品在线观看 | 成年人免费av网站 | 久久开心激情 | 亚洲综合成人婷婷小说 | 天天骚夜夜操 | 中文字幕在线观看你懂的 | 夜夜躁日日躁狠狠久久88av | 中文字幕av网站 | 久久久久久久久久久久电影 | 久草精品视频 | 久久精品视频网址 | 日韩国产精品一区 | 国产97在线播放 | 99麻豆久久久国产精品免费 | 狠狠操夜夜| 色窝资源 | 日韩免费看 | 91久久爱热色涩涩 | 日韩美精品视频 | 国产九九热| 性色av香蕉一区二区 | 伊人久久在线观看 | 精品理论片 | 日韩av影视 | 欧美日bb | 国产99久久久国产精品免费看 | 99视频在线免费 | 亚洲欧美国产视频 | 国产三级在线播放 | 在线观看黄色大片 | 亚洲精品国产成人av在线 | 国内精品美女在线观看 | 成人在线视| 久久精品高清视频 | 手机在线永久免费观看av片 | 国产精品精品久久久 | av黄免费看 | 久草在线看片 | 蜜臀aⅴ国产精品久久久国产 | 操少妇视频| 色噜噜日韩精品欧美一区二区 | 黄色大片av | 热久久影视 | 国产黄色免费 | 99免费观看视频 | 激情久久五月 | 亚洲午夜精 | 久久夜夜夜 | 亚洲视频aaa | av大片免费看 | 亚洲国产精品久久久久 | av在线不卡观看 | 美女精品久久久 | 在线视频 国产 日韩 | 国产成人精品一二三区 | 国产精品免费在线播放 | 久草热久草视频 | 成人一级电影在线观看 | 一区二区精品视频 | 国产999精品久久久久久 | 国产精品视屏 | 毛片99 | 2019精品手机国产品在线 | 日韩久久一区 | 亚洲精品国产综合久久 | 搡bbbb搡bbb视频 | 亚洲精品视频久久 | 日韩综合精品 | 国产精品一区在线 | 久色小说 | 在线观看久久 | 99久久婷婷国产综合精品 | 欧美乱码精品一区 | 国产亚洲精品综合一区91 | 色婷在线 | 看片的网址 | 久草在线最新免费 | 四虎海外影库www4hu | 99国产视频 | 国产一区二区三区黄 | 丁香影院在线 | 天天干天天操天天入 | 一区二区久久 | 中文字幕视频一区二区 | 久久婷婷色综合 | 成人网页在线免费观看 | 久久神马影院 | 国产麻豆视频在线观看 | 激情综合站| 亚洲成人国产精品 | 三级在线视频观看 | www.亚洲激情.com | 天天操人人干 | 不卡国产在线 | 国产免码va在线观看免费 | 久久午夜羞羞影院 | 激情欧美日韩一区二区 | 午夜在线看片 | 国产视频在线观看免费 | 久久亚洲影院 | 九九亚洲视频 | 久久6精品 | 国产高清 不卡 | 国产黄色片一级 | 6699私人影院 | 久久全国免费视频 | 国产精品18久久久久久久久 | av一区二区三区在线播放 | 欧美精品xx| 99久久99久久精品国产片 | 欧美片一区二区三区 | 91在线视频在线观看 | 久久久久久久久久久福利 | 韩国av一区二区三区 | 国产精品久久久久久久久久久杏吧 | 免费av网址在线观看 | 国内精品久久久久 | 99欧美精品| 中文字幕色播 | 色综合久久五月 | 欧美日韩在线免费观看 | 久久看毛片 | 国产精品9区 | 久草在线观看 | 婷婷激情五月 | 午夜久久久精品 | 天天操狠狠操网站 | 福利网址在线观看 | 最近中文字幕在线中文高清版 | 色婷婷88av视频一二三区 | 一区国产精品 | 九九热久久免费视频 | 99色亚洲 | 亚洲精品在线看 | 亚洲夜夜网 | 国产一区二区三区在线 | 日韩免费一区二区三区 | 天天干天天插 | 激情欧美在线观看 | 人成免费网站 | 国产99精品在线观看 | 成人在线观看日韩 | 成人资源在线 | 91在线看视频免费 | www.天天射.com| 久久国产精品免费看 | 中文字幕在线免费看 | 精品国产乱码久久 | 欧美精品首页 | 青青河边草观看完整版高清 | 97网| 亚洲欧美日韩在线看 | 狠狠色丁香 | 亚洲手机av | 久久99精品久久久久久久久久久久 | 欧洲视频一区 | 亚洲精选视频免费看 | 97超碰影视| 久久精品国产免费观看 | 国产精品va在线播放 | 亚洲精品美女久久久 | 黄色三级免费网址 | 精品视频www | 欧美精品久久久久久久亚洲调教 | 亚洲一区二区三区在线看 | 久久这里只有精品23 | 久久久久 | 天天插天天操天天干 | 99久久精品免费看 | 成人av.com | 久久av中文字幕片 | 九九国产精品视频 | 亚洲精品在线一区二区三区 | 亚洲专区欧美专区 | 天天弄天天干 | 欧美极品少妇xxxxⅹ欧美极品少妇xxxx亚洲精品 | 天海翼一区二区三区免费 | 国产黄网站在线观看 | 日韩在线视频网站 | 久久福利国产 | 欧美一区二区三区免费看 | 国内外成人免费在线视频 | 免费日韩一级片 | a级片在线播放 | 在线观看www91 | avav99| 中文字幕国产一区二区 | 99色国产 | 中文字幕在线一二 | 久久99欧美 | av观看免费在线 | 久久久精品国产一区二区 | 天天爱天天草 | 日韩v欧美v日本v亚洲v国产v | 成人久久久久久久久久 | 不卡国产视频 | 久久综合视频网 | 国产高清一区二区 | 在线观看一区视频 | 日韩一级黄色大片 | 国产一区免费在线 | 免费观看91视频大全 | 国产成人亚洲在线观看 | 99精品国产亚洲 | 国产又粗又猛又黄又爽视频 | 久久9视频 | 免费a一级 | 狠狠色狠狠色综合系列 | 国产麻豆精品一区 | 久久精品成人欧美大片古装 | 97在线免费视频观看 | 久久精品激情 | 97色在线观看 | 成人中文字幕+乱码+中文字幕 | 国产馆在线播放 | 国产日韩视频在线观看 | 精品视频 | 日韩小视频 | 91精品在线视频观看 | 日韩欧美综合视频 | 黄色成人毛片 | 国产一卡久久电影永久 | 91cn国产在线 | 国产精品久久久久久久久久新婚 | 欧美一级高清片 | 九九热免费精品视频 | 欧美专区亚洲专区 | 99视频在线观看免费 | 日韩欧美一区二区三区视频 | 91精品在线免费 | 欧美日韩一区二区在线观看 | www黄色软件 | 久久精品播放 | 在线观看精品 | 93久久精品日日躁夜夜躁欧美 | 亚洲成人av影片 | 国产黄免费 | 日本中文不卡 | 四虎影视成人永久免费观看亚洲欧美 | 久久视频国产 | 日本mv大片欧洲mv大片 | 伊人五月在线 | 色综合天天综合在线视频 | 色在线免费观看 | 高清视频一区二区三区 | 在线观看完整版免费 | 男女精品久久 | 成人免费在线观看av | 亚洲综合色视频 | 这里只有精品视频在线观看 | 国产精品一区二区三区在线播放 | 免费看搞黄视频网站 | 欧美日韩精品在线观看 | 日日夜夜操操操操 | av一区二区三区在线播放 | 国产.精品.日韩.另类.中文.在线.播放 | 在线观看日韩一区 | www.伊人网 | 国产视频精品免费 | 日韩一二三在线 | 视频一区二区视频 | 四虎国产视频 | 天天综合狠狠精品 | 国产精品免费观看久久 | www.狠狠插.com | 国产电影一区二区三区四区 | 一区二区 不卡 | 能在线看的av| 日韩综合一区二区三区 | 日韩av播放在线 | 天天干天天插伊人网 | 国产精品毛片一区视频播不卡 | 2023av在线| 999国产| 91视频免费网址 | 久久久久久久综合色一本 | 国产伦理一区 | 在线观看一区 | 久久久国产精品免费 | 免费在线激情视频 | 欧美精品一区二区蜜臀亚洲 | 伊人影院av | 色综合天天天天做夜夜夜夜做 | 精品在线观看国产 | 国产免费人成xvideos视频 | 美女视频黄免费 | 91大神在线观看视频 | 久久久久久久久久久免费av | 精品 激情 | 激情视频国产 | 国内成人av| 九九热精品国产 | 国产一级黄色电影 | 国产精品美女久久久免费 | 91精品国产入口 | 玖玖在线视频观看 | 久久免费视频在线 | h视频日本 | 久久人人添人人爽添人人88v | 久久视频网 | 久久新 | 天天色天天爱天天射综合 | 97人人模人人爽人人喊中文字 | 亚洲精品在线视频播放 | 国产日韩精品久久 | 激情图片qvod | 88av视频 | 在线免费观看视频一区二区三区 | 福利在线看片 | 免费网站黄 | 国产色视频一区二区三区qq号 | 97精品在线 | 久久久久免费观看 | 91亚洲狠狠婷婷综合久久久 | 一区二区三区不卡在线 | 欧美日韩一区二区三区不卡 | 91成人看片 | 97干com| 国产福利免费看 | 91精品久久香蕉国产线看观看 | 久久久久激情电影 | 久久爱综合 | 欧美精品国产综合久久 | 日韩视频免费观看高清完整版在线 | av电影免费看 | 91三级在线观看 | 国产精品久久久久久久久搜平片 | 97综合网 | 国产亚洲精品久久久久久大师 | 91av精品 | 欧美精品中文在线免费观看 | 国产精华国产精品 | 欧美一区二区三区四区夜夜大片 | 欧美成人性网 | 91人人人| 国产精品网红直播 | 国产精品乱码高清在线看 | 97成人免费视频 | 国产精品毛片一区二区 | 国产成人在线观看 | 成人在线播放网站 | 91精品秘密在线观看 | 久久在线精品视频 | 国产精品96久久久久久吹潮 | 99热这里只有精品8 久久综合毛片 | 中文字幕在线看视频国产中文版 | 久久久久亚洲精品中文字幕 | 国产高清av免费在线观看 | 亚洲精品国产品国语在线 | 2019中文字幕网站 | 黄色av免费看 | 精品久久久久久久久久久久久久久久久久 | 久久成人精品视频 | 国产美女视频黄a视频免费 久久综合九色欧美综合狠狠 | 日韩 在线 | 日韩美女一级片 | 欧美日韩高清国产 | 黄色精品一区 | 欧美成人精品欧美一级乱 | 999抗病毒口服液 | 99色婷婷 | 国产在线无 | 免费在线观看午夜视频 | av片一区二区 | 美女激情影院 | 在线视频1卡二卡三卡 | 亚洲精品久久久久久久不卡四虎 | www.亚洲精品视频 | 国产亚洲欧美在线视频 | 免费观看版 | 国产日韩三级 | 中文字幕一区二区三区四区 | 中文字幕一区二区三区在线播放 | 免费观看版| 久久久久久久久久久影视 | 久草视频国产 | 狠狠干狠狠艹 | 五月天六月婷 | 综合天天色 | 97影视| av在线com | 久久精品79国产精品 | 成人教育av | 成年人免费在线 | 久久观看最新视频 | 日韩av免费在线电影 | 激情xxxx| 久草在线视频中文 | 三级午夜片 | 久久公开免费视频 | 激情欧美一区二区三区 | 亚洲伊人第一页 | 欧美日韩亚洲在线观看 | 国产一级免费视频 | 久热免费| 一区二区 精品 | 久久国产精品小视频 | 久久综合一本 | 丁香亚洲 | 中文在线免费观看 | 亚洲国产精久久久久久久 | 亚洲va欧美va国产va黑人 | 婷色在线| 黄色官网在线观看 | 日韩在线播放av | 99超碰在线观看 | 激情欧美一区二区免费视频 | 亚洲在线免费视频 | av福利资源| 日韩视频在线观看视频 | 国产午夜精品免费一区二区三区视频 | 久久国产三级 | 天天弄天天干 | 人人爱人人射 | 国产精品美女久久久久久网站 | 成人免费观看大片 | 亚洲精品视频www | 日韩三级.com | 欧美久久综合 | 4438全国亚洲精品在线观看视频 | 中文字幕免费播放 | 日韩免费在线 | 91大神一区二区三区 | 在线欧美日韩 | 欧美激情精品久久久久久变态 | 亚洲亚洲精品在线观看 | 国产一区视频导航 | 国产精品毛片一区二区 | 丁香九月激情综合 | 色夜影院| 99久久精品视频免费 | 天天插天天色 | 亚洲视频播放 | 亚洲国产一区在线观看 | av在线免费观看黄 | 日韩视频一二三区 | 久久综合加勒比 | 中文字幕av免费在线观看 | 日韩免费观看一区二区三区 | 亚洲精品资源在线 | 久草在线资源观看 | 久久 国产一区 | 免费91在线 | 亚洲精品免费视频 | 在线视频观看91 | 亚洲午夜大片 | 久久精品99久久久久久2456 | 国产视频亚洲视频 | 久草免费新视频 | 亚洲精品日韩av | www91在线| 亚洲精品黄色 | 在线中文字幕一区二区 | av三区在线| 五月婷综合 | 91视频电影 | 久久精品直播 | 欧美日韩久 | 国产精品国产三级国产aⅴ入口 | 国产1区2区3区精品美女 | 欧美精品亚洲精品日韩精品 | www.xxxx欧美 | 国产精品9区 | 婷婷色在线播放 | 成人av免费电影 | 亚洲黄色在线播放 | 91麻豆视频网站 | 久久96国产精品久久99软件 |