js代碼規(guī)范

總體規(guī)范

  • switch 下的 case 和 default 必須增加一個縮進層級

  • 二元運算符兩側(cè)必須有一個空格,一元運算符與操作對象之間不允許有空格

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

  • if / else / for / while / function / switch / do / try / catch / finally關(guān)鍵字后,必須有一個空格

  • 在對象創(chuàng)建時,屬性中的:之后必須有空格,:之前不允許有空格

      var obj = {
          a: 1,
          b: 2,
          c: 3
      };
    
      // bad
      var obj = {
          a : 1,
          b:2,
          c :3
      };
    
  • 函數(shù)聲明、具名函數(shù)表達式、函數(shù)調(diào)用中,函數(shù)名和(之間不允許有空格

  • ,;前不允許有空格

  • 在函數(shù)調(diào)用、函數(shù)聲明、括號表達式、屬性訪問、if / for / while / switch / catch 等語句中,() 和 [] 內(nèi)緊貼括號部分不允許有空格

      // 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-- ) {
      }
    
  • 單行聲明的數(shù)組與對象,如果包含元素,{}[]內(nèi)緊貼括號部分不允許包含空格

  • 行尾不得有多余的空格

  • 運算符處換行時,運算符必須在新行的行首

      // 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;
    
  • 在函數(shù)聲明、函數(shù)表達式、函數(shù)調(diào)用、對象創(chuàng)建、數(shù)組創(chuàng)建、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
      );
    
  • 不同行為或邏輯的語句集,使用空行隔開,更易閱讀

  • 較復(fù)雜的邏輯條件組合,將每個條件獨立一行,邏輯運算符放置在行首進行分隔,或?qū)⒉糠诌壿嫲催壿嫿M合進行分隔。

  • 建議最終將右括號 )與左大括號{ 放在獨立一行,保證與 if 內(nèi)語句塊能容易視覺辨識。

     if (user.isAuthenticated()
         && user.isInRole('admin')
         && user.hasAuthority('add-admin')
         || user.hasAuthority('delete-admin')
     ) {
         // Code
     }
    
  • 按一定長度截斷字符串,并使用 + 運算符進行連接。

  • 分隔字符串盡量按語義進行,如不要在一個完整的名詞中間斷開。

  • 特別的,對于HTML片段的拼接,通過縮進,保持和HTML相同的結(jié)構(gòu)。
    也可使用數(shù)組來進行拼接,相對 + 更容易調(diào)整縮進。

      var html = [
         '<article>',
             '<h1>Title here</h1>',
             '<p>This is a paragraph</p>',
             '<footer>Complete</footer>',
         '</article>'
     ];
     html = html.join('');
    
  • 當(dāng)參數(shù)過多時,將每個參數(shù)獨立寫在一行上,并將結(jié)束的右括號 )獨立一行。

  • 所有參數(shù)必須增加一個縮進。

      foo(
          aVeryVeryLongArgument,
          anotherVeryLongArgument,
          callback
      );
    

也可以按邏輯對參數(shù)進行組合。
最經(jīng)典的是baidu.format函數(shù),調(diào)用時將參數(shù)分為“模板”和“數(shù)據(jù)”兩塊

    baidu.format(
        dateFormatTemplate,
        year, month, date, hour, minute, second
    );

當(dāng)函數(shù)調(diào)用時,如果有一個或以上參數(shù)跨越多行,應(yīng)當(dāng)每一個參數(shù)獨立一行。
這通常出現(xiàn)在匿名函數(shù)或者對象初始化等作為參數(shù)時,如setTimeout函數(shù)等。

    setTimeout(
        function () {
            alert('hello');
        },
        200
    );

    order.data.read(
        'id=' + me.model.id, 
        function (data) {
            me.attchToModel(data.result);
            callback();
        }, 
        300
    );
  • 鏈?zhǔn)秸{(diào)用較長時采用縮進進行調(diào)整。

     $('#items')
         .find('.selected')
         .highlight()
         .end();
    
  • 三元運算符由3部分組成,因此其換行應(yīng)當(dāng)根據(jù)每個部分的長度不同,形成不同的情況。

     var result = thisIsAVeryVeryLongCondition
         ? resultA : resultB;
    
     var result = condition
         ? thisIsAVeryVeryLongResult
         : resultB;
    
  • 數(shù)組和對象初始化的混用,嚴(yán)格按照每個對象的 { 和結(jié)束 } 在獨立一行的風(fēng)格書寫。

     var array = [
         {
             // ...
         },
         {
             // ...
         }
     ];
    

對于 if...else...、try...catch...finally等語句,推薦使用在}號后添加一個換行 的風(fēng)格,使代碼層次結(jié)構(gòu)更清晰,閱讀性更好。

  • 不得省略語句結(jié)束的分號
    在 if / else / for / do / while 語句中,即使只有一行,也不得省略塊{...}

  • 函數(shù)定義結(jié)束不允許添加分號

  • IIFE 必須在函數(shù)表達式外添加 (,非 IIFE 不得在函數(shù)表達式外添加 (
    額外的 ( 能夠讓代碼在閱讀的一開始就能判斷函數(shù)是否立即被調(diào)用,進而明白接下來代碼的用途。而不是一直拖到底部才恍然大悟。

命名

  • 變量 使用 Camel命名法

  • 常量 使用 全部字母大寫,單詞間下劃線分隔 的命名方式

  • 類 使用 Pascal命名法

      function TextNode(options) {
      }
    
  • 類的 方法 / 屬性 使用 Camel命名法

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

  • 由多個單詞組成的縮寫詞,在命名中,根據(jù)當(dāng)前命名法和出現(xiàn)的位置,所有字母的大小寫與首字母的大小寫保持一致。

  • 由多個單詞組成的縮寫詞,在命名中,根據(jù)當(dāng)前命名法和出現(xiàn)的位置,所有字母的大小寫與首字母的大小寫保持一致

     function XMLParser() {
     }
    
     function insertHTML(element, html) {
     }
    
     var httpRequest = new HTTPRequest();
    
  • 類名 使用 名詞

  • 函數(shù)名 使用 動賓短語

  • boolean 類型的變量使用 is 或 has 開頭

  • Promise對象 用 動賓短語的進行時 表達

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

注釋

  • 單行注釋
    必須獨占一行。// 后跟一個空格,縮進與下一行被注釋說明的代碼一致。

  • 多行注釋
    避免使用 /.../ 這樣的多行注釋。有多行注釋內(nèi)容時,使用多個單行注釋

  • 文檔化注釋
    為了便于代碼閱讀和自文檔化,以下內(nèi)容必須包含以 /*.../ 形式的塊注釋中

    文檔注釋前必須空一行
    自文檔化的文檔說明 what,而不是 how

  • 文件頂部必須包含文件注釋,用 @file 標(biāo)識文件說明
    文件注釋中可以用 @author 標(biāo)識開發(fā)者信息

  • 命名空間使用 @namespace 標(biāo)識。

示例:

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

類和構(gòu)造函數(shù)

  • 使用 @class 標(biāo)記類或構(gòu)造函數(shù)。
    解釋:
    對于使用對象 constructor 屬性來定義的構(gòu)造函數(shù),可以使用 @constructor 來標(biāo)記。

示例:

    /**
     * 描述
     *
     * @class
     */
    function Developer() {
        // constructor body
    }
  • 使用 @extends 標(biāo)記類的繼承信息。

示例:

    /**
     * 描述
     *
     * @class
     * @extends Developer
     */
    function Fronteer() {
        Developer.call(this);
        // constructor body
    }
    util.inherits(Fronteer, Developer);
  • 使用包裝方式擴展類成員時, 必須通過 @lends 進行重新指向.沒有 @lends 標(biāo)記將無法為該類生成包含擴展類成員的文檔。

示例:

    /**
     * 類描述
     *
     * @class
     * @extends Developer
     */
    function Fronteer() {
        Developer.call(this);
        // constructor body
    }

    util.extend(
        Fronteer.prototype,
        /** @lends Fronteer.prototype */{
            _getLevel: function () {
                // TODO
            }
        }
    );
  • 類的屬性或方法等成員信息使用 @public / @protected / @private 中的任意一個,指明可訪問性。
    解釋:
    生成的文檔中將有可訪問性的標(biāo)記,避免用戶直接使用非 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 () {
    };
函數(shù)/方法注釋

函數(shù)/方法注釋必須包含函數(shù)說明,有參數(shù)和返回值時必須使用注釋標(biāo)識
參數(shù)和返回值注釋必須包含類型信息和說明

    // null 或 undefined

    // good
    if (noValue == null) {
      // ......
    }

    // bad
    if (noValue === null || typeof noValue === 'undefined') {
      // ......
    }
如果函數(shù)或全局中的 else 塊后沒有任何語句,可以刪除 else。
    // good
    function getName() {
        if (name) {
            return name;
        }

        return 'unnamed';
    }

    // bad
    function getName() {
        if (name) {
            return name;
        }
        else {
            return 'unnamed';
        }
    }
對循環(huán)內(nèi)多次使用的不變值,在循環(huán)外用變量緩存
    // 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';
        // ......
    }
對有序集合進行順序無關(guān)的遍歷時,使用逆序遍歷。

解釋:
逆序遍歷可以節(jié)省變量,代碼比較優(yōu)化。

示例:

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

類型轉(zhuǎn)換檢測

  • 類型檢測優(yōu)先使用typeof。對象類型檢測使用 instanceof。nullundefined 的檢測使用 == null

  • 轉(zhuǎn)換成 string 時,使用 + ''。

示例:

    // good
    num + '';

    // bad
    new String(num);
    num.toString();
    String(num);
  • 轉(zhuǎn)換成 number 時,通常使用 +。

示例:

    // good
      +str;

    // bad
    Number(str);
  • string 轉(zhuǎn)換成 number,要轉(zhuǎn)換的字符串結(jié)尾包含非數(shù)字并期望忽略時,使用 parseInt。

示例:

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

示例:

    // good
    parseInt(str, 10);

    // bad
    parseInt(str);
  • 轉(zhuǎn)換成 boolean 時,使用 !!。

示例:

    var num = 3.14;
    !!num;
  • number 去除小數(shù)點,使用 Math.floor / Math.round / Math.ceil,不使用 parseInt。

示例:

    // good
    var num = 3.14;
    Math.ceil(num);

    // bad
    var num = 3.14;
    parseInt(num, 10);

字符串

  • 字符串開頭和結(jié)束使用單引號 '。
    解釋:
    輸入單引號不需要按住 shift,方便輸入。
    實際使用中,字符串經(jīng)常用來拼接 HTML。為方便 HTML 中包含雙引號而不需要轉(zhuǎn)義寫法。
    示例:

      var str = '我是一個字符串';
      var html = '<div class="cls">拼接HTML可以省去雙引號轉(zhuǎn)義</div>';
    
  • 使用 數(shù)組 或 + 拼接字符串。
    解釋:
    使用 + 拼接字符串,如果拼接的全部是 StringLiteral,壓縮工具可以對其進行自動合并的優(yōu)化。所以,靜態(tài)字符串建議使用 + 拼接。
    在現(xiàn)代瀏覽器下,使用 + 拼接字符串,性能較數(shù)組的方式要高。
    如需要兼顧老舊瀏覽器,應(yīng)盡量使用數(shù)組拼接字符串。
    示例:

      // 使用數(shù)組拼接字符串
      var str = [
          // 推薦換行開始并縮進開始第一個字符串, 對齊代碼, 方便閱讀.
          '<ul>',
              '<li>第一項</li>',
              '<li>第二項</li>',
          '</ul>'
        ].join('');
    
      // 使用 + 拼接字符串
      var str2 = '' // 建議第一個為空字符串, 第二個換行開始并縮進開始, 對齊代碼, 方便閱讀
          + '<ul>',
          +    '<li>第一項</li>',
          +    '<li>第二項</li>',
          + '</ul>';
    

對象

  • 使用對象字面量 {} 創(chuàng)建新 Object。

示例:

    // good
    var obj = {};

    // bad
    var obj = new Object();
  • 對象創(chuàng)建時,如果一個對象的所有 屬性 均可以不添加引號,則所有 屬性 不得添加引號。

示例:

    var info = {
        name: 'someone',
        age: 28
    };
  • 對象創(chuàng)建時,如果任何一個 屬性 需要添加引號,則所有 屬性 必須添加 '。
    解釋:
    如果屬性不符合 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];
        }
    }

數(shù)組

使用數(shù)組字面量[]創(chuàng)建新數(shù)組,除非想要創(chuàng)建的是指定長度的數(shù)組。

示例:

    // good
    var arr = [];

    // bad
    var arr = new Array();
  • 遍歷數(shù)組不使用 for in。
    解釋:
    數(shù)組對象可能存在數(shù)字以外的屬性, 這種情況下 for in 不會得到正確結(jié)果.

示例:

    var arr = ['a', 'b', 'c'];
    arr.other = 'other things'; // 這里僅作演示, 實際中應(yīng)使用Object類型

    // 正確的遍歷方式
      for (var i = 0, len = arr.length; i < len; i++) {
        console.log(i);
    }

    // 錯誤的遍歷方式
      for (i in arr) {
        console.log(i);
    }
  • 不因為性能的原因自己實現(xiàn)數(shù)組排序功能,盡量使用數(shù)組的 sort 方法。
    解釋:
    自己實現(xiàn)的常規(guī)排序算法,在性能上并不優(yōu)于數(shù)組默認(rèn)的 sort 方法。以下兩種場景可以自己實現(xiàn)排序:

  • 需要穩(wěn)定的排序算法,達到嚴(yán)格一致的排序結(jié)果。
    數(shù)據(jù)特點鮮明,適合使用桶排。

  • 清空數(shù)組使用 .length = 0。

函數(shù)
  • 一個函數(shù)的長度控制在 50 行以內(nèi)。
    解釋:
    將過多的邏輯單元混在一個大函數(shù)中,易導(dǎo)致難以維護。一個清晰易懂的函數(shù)應(yīng)該完成單一的邏輯單元。復(fù)雜的操作應(yīng)進一步抽取,通過函數(shù)的調(diào)用來體現(xiàn)流程。

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

  • 一個函數(shù)的參數(shù)控制在 6 個以內(nèi)。
    解釋:
    除去不定長參數(shù)以外,函數(shù)具備不同邏輯意義的參數(shù)建議控制在 6 個以內(nèi),過多參數(shù)會導(dǎo)致維護難度增大。

  • 某些情況下,如使用 AMD Loader 的 require 加載多個模塊時,其 callback 可能會存在較多參數(shù),因此對函數(shù)參數(shù)的個數(shù)不做強制限制。

  • 空函數(shù)不使用 new Function() 的形式。

示例:

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

示例:

    var EMPTY_FUNCTION = function () {};

    function MyClass() {
    }

    MyClass.prototype.abstractMethod = EMPTY_FUNCTION;
    MyClass.prototype.hooks.before = EMPTY_FUNCTION;
    MyClass.prototype.hooks.after = EMPTY_FUNCTION;

元素樣式style

  • 盡可能通過為元素添加預(yù)定義的 className 來改變元素樣式,避免直接操作 style 設(shè)置

  • 通過 style 對象設(shè)置元素樣式時,對于帶單位非 0 值的屬性,不允許省略單位

之前寫的筆記,想要再找原文,找不到了。。只是知識的搬運工。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 原文: https://github.com/ecomfe/spec/blob/master/javascript...
    zock閱讀 3,498評論 2 36
  • 第5章 引用類型(返回首頁) 本章內(nèi)容 使用對象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類型 使用基本類型...
    大學(xué)一百閱讀 3,692評論 0 4
  • JavaScript編碼規(guī)范 1 前言 [2 代碼風(fēng)格] [2.1 文件] [2.2 結(jié)構(gòu)] [2.2.1 縮進]...
    憶飛閱讀 1,216評論 1 2
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,711評論 19 139
  • 人間歲月不饒人, 低唱情歌兩三首。 往事回首物依舊, 時光昔人卻白頭。
    書南Q閱讀 368評論 1 9

友情鏈接更多精彩內(nèi)容