Javascript Code Style Guide

本指南採用的Airbnb發佈的基於ES5的JavaScript Code Style。javascript

ES5 英文版:https://github.com/airbnb/javascript/tree/es5-deprecated/es5css

ES5 中文版:https://github.com/sivan/javascript-style-guide/blob/master/es5/README.mdhtml

 

修改點:java

  1. 原指南要求採用2個空格的縮進,而NetBrain採用4個空格的縮進。

 

目錄jquery

類型

  • 原始值: 存取直接做用於它自身。git

    • string
    • number
    • boolean
    • null
    • undefined

     

    var foo = 1;
    var bar = foo;
    
    bar = 9;
    
    console.log(foo, bar); // => 1, 9

     

  • 複雜類型: 存取時做用於它自身值的引用。github

    • object
    • array
    • function
     
    var foo = [1, 2];
    var bar = foo;
    
    bar[0] = 9;
    
    console.log(foo[0], bar[0]); // => 9, 9

     

對象

  • 使用直接量建立對象。web

     

    // bad
    var item = new Object();
    
    // good
    var item = {};

     

  • 不要使用保留字做爲鍵名,它們在 IE8 下不工做。更多信息express

     

    // bad
    var superman = {
      default: { clark: 'kent' },
      private: true
    };
    
    // good
    var superman = {
      defaults: { clark: 'kent' },
      hidden: true
    };

     

  • 使用同義詞替換須要使用的保留字。數組

     

    // bad
    var superman = {
      class: 'alien'
    };
    
    // bad
    var superman = {
      klass: 'alien'
    };
    
    // good
    var superman = {
      type: 'alien'
    };

     

數組

  • 使用直接量建立數組。

     

    // bad
    var items = new Array();
    
    // good
    var items = [];

     

  • 向數組增長元素時使用 Array#push 來替代直接賦值。

     

    var someStack = [];
    
    
    // bad
    someStack[someStack.length] = 'abracadabra';
    
    // good
    someStack.push('abracadabra');

     

  • 當你須要拷貝數組時,使用 Array#slice。jsPerf

     

    var len = items.length;
    var itemsCopy = [];
    var i;
    
    // bad
    for (i = 0; i < len; i++) {
      itemsCopy[i] = items[i];
    }
    
    // good
    itemsCopy = items.slice();

     

  • 使用 Array#slice 將類數組對象轉換成數組。

     

    function trigger() {
      var args = Array.prototype.slice.call(arguments);
      ...
    }

     

字符串

  • 使用單引號 '' 包裹字符串。

     

    // bad
    var name = "Bob Parr";
    
    // good
    var name = 'Bob Parr';
    
    // bad
    var fullName = "Bob " + this.lastName;
    
    // good
    var fullName = 'Bob ' + this.lastName;

     

  • 超過 100 個字符的字符串應該使用鏈接符寫成多行。

  • 注:若過分使用,經過鏈接符鏈接的長字符串可能會影響性能。jsPerf & 討論.

     

    // bad
    var errorMessage = 'This is a super long error that was thrown because of Batman. When you stop to think about how Batman had anything to do with this, you would get nowhere fast.';
    
    // bad
    var errorMessage = 'This is a super long error that was thrown because \
    of Batman. When you stop to think about how Batman had anything to do \
    with this, you would get nowhere \
    fast.';
    
    // good
    var errorMessage = 'This is a super long error that was thrown because ' +
      'of Batman. When you stop to think about how Batman had anything to do ' +
      'with this, you would get nowhere fast.';

     

  • 程序化生成的字符串使用 Array#join 鏈接而不是使用鏈接符。尤爲是 IE 下:jsPerf.

     

    var items;
    var messages;
    var length;
    var i;
    
    messages = [{
      state: 'success',
      message: 'This one worked.'
    }, {
      state: 'success',
      message: 'This one worked as well.'
    }, {
      state: 'error',
      message: 'This one did not work.'
    }];
    
    length = messages.length;
    
    // bad
    function inbox(messages) {
      items = '<ul>';
    
      for (i = 0; i < length; i++) {
        items += '<li>' + messages[i].message + '</li>';
      }
    
      return items + '</ul>';
    }
    
    // good
    function inbox(messages) {
      items = [];
    
      for (i = 0; i < length; i++) {
        // use direct assignment in this case because we're micro-optimizing.
        items[i] = '<li>' + messages[i].message + '</li>';
      }
    
      return '<ul>' + items.join('') + '</ul>';
    }

     

函數

  • 函數表達式:

     

    // 匿名函數表達式
    var anonymous = function() {
      return true;
    };
    
    // 命名函數表達式
    var named = function named() {
      return true;
    };
    
    // 當即調用的函數表達式(IIFE)
    (function () {
      console.log('Welcome to the Internet. Please follow me.');
    }());

     

  • 永遠不要在一個非函數代碼塊(if、while 等)中聲明一個函數,把那個函數賦給一個變量。瀏覽器容許你這麼作,但它們的解析表現不一致。

  • 注: ECMA-262 把  定義爲一組語句。函數聲明不是語句。閱讀對 ECMA-262 這個問題的說明

     

    // bad
    if (currentUser) {
      function test() {
        console.log('Nope.');
      }
    }
    
    // good
    var test;
    if (currentUser) {
      test = function test() {
        console.log('Yup.');
      };
    }

     

  • 永遠不要把參數命名爲 arguments。這將取代函數做用域內的 arguments 對象。

     

    // bad
    function nope(name, options, arguments) {
      // ...stuff...
    }
    
    // good
    function yup(name, options, args) {
      // ...stuff...
    }

     

屬性

  • 使用 . 來訪問對象的屬性。

     

    var luke = {
      jedi: true,
      age: 28
    };
    
    // bad
    var isJedi = luke['jedi'];
    
    // good
    var isJedi = luke.jedi;

     

  • 當經過變量訪問屬性時使用中括號 []

     

    var luke = {
      jedi: true,
      age: 28
    };
    
    function getProp(prop) {
      return luke[prop];
    }
    
    var isJedi = getProp('jedi');

     

⬆ 回到頂部

變量

  • 老是使用 var 來聲明變量。不這麼作將致使產生全局變量。咱們要避免污染全局命名空間。

     

    // bad
    superPower = new SuperPower();
    
    // good
    var superPower = new SuperPower();

     

  • 使用 var 聲明每個變量。 這樣作的好處是增長新變量將變的更加容易,並且你永遠不用再擔憂調換錯 ; 跟 ,

     

    // bad
    var items = getItems(),
        goSportsTeam = true,
        dragonball = 'z';
    
    // bad
    // (跟上面的代碼比較一下,看看哪裏錯了)
    var items = getItems(),
        goSportsTeam = true;
        dragonball = 'z';
    
    // good
    var items = getItems();
    var goSportsTeam = true;
    var dragonball = 'z';

     

  • 最後再聲明未賦值的變量。當你須要引用前面的變量賦值時這將變的頗有用。

     

    // bad
    var i, len, dragonball,
        items = getItems(),
        goSportsTeam = true;
    
    // bad
    var i;
    var items = getItems();
    var dragonball;
    var goSportsTeam = true;
    var len;
    
    // good
    var items = getItems();
    var goSportsTeam = true;
    var dragonball;
    var length;
    var i;

     

  • 在做用域頂部聲明變量。這將幫你避免變量聲明提高相關的問題。

     

    // bad
    function () {
      test();
      console.log('doing stuff..');
    
      //..other stuff..
    
      var name = getName();
    
      if (name === 'test') {
        return false;
      }
    
      return name;
    }
    
    // good
    function () {
      var name = getName();
    
      test();
      console.log('doing stuff..');
    
      //..other stuff..
    
      if (name === 'test') {
        return false;
      }
    
      return name;
    }
    
    // bad - 沒必要要的函數調用
    function () {
      var name = getName();
    
      if (!arguments.length) {
        return false;
      }
    
      this.setFirstName(name);
    
      return true;
    }
    
    // good
    function () {
      var name;
    
      if (!arguments.length) {
        return false;
      }
    
      name = getName();
      this.setFirstName(name);
    
      return true;
    }

     

提高

  • 變量聲明會提高至做用域頂部,但賦值不會。

     

    // 咱們知道這樣不能正常工做(假設這裏沒有名爲 notDefined 的全局變量)
    function example() {
      console.log(notDefined); // => throws a ReferenceError
    }
    
    // 但因爲變量聲明提高的緣由,在一個變量引用後再建立它的變量聲明將能夠正常工做。
    // 注:變量賦值爲 `true` 不會提高。
    function example() {
      console.log(declaredButNotAssigned); // => undefined
      var declaredButNotAssigned = true;
    }
    
    // 解釋器會把變量聲明提高到做用域頂部,意味着咱們的例子將被重寫成:
    function example() {
      var declaredButNotAssigned;
      console.log(declaredButNotAssigned); // => undefined
      declaredButNotAssigned = true;
    }

     

  • 匿名函數表達式會提高它們的變量名,但不會提高函數的賦值。

     

    function example() {
      console.log(anonymous); // => undefined
    
      anonymous(); // => TypeError anonymous is not a function
    
      var anonymous = function () {
        console.log('anonymous function expression');
      };
    }

     

  • 命名函數表達式會提高變量名,但不會提高函數名或函數體。

     

    function example() {
      console.log(named); // => undefined
    
      named(); // => TypeError named is not a function
    
      superPower(); // => ReferenceError superPower is not defined
    
      var named = function superPower() {
        console.log('Flying');
      };
    }
    
    // 當函數名跟變量名同樣時,表現也是如此。
    function example() {
      console.log(named); // => undefined
    
      named(); // => TypeError named is not a function
    
      var named = function named() {
        console.log('named');
      }
    }

     

  • 函數聲明提高它們的名字和函數體。

     

    function example() {
      superPower(); // => Flying
    
      function superPower() {
        console.log('Flying');
      }
    }

     

  • 瞭解更多信息在 JavaScript Scoping & Hoisting by Ben Cherry.

比較運算符 & 等號

  • 優先使用 === 和 !== 而不是 == 和 !=.

  • 條件表達式例如 if 語句經過抽象方法 ToBoolean 強制計算它們的表達式而且老是遵照下面的規則:

    • 對象 被計算爲 true
    • Undefined 被計算爲 false
    • Null 被計算爲 false
    • 布爾值 被計算爲 布爾的值
    • 數字 若是是 +0、-0 或 NaN 被計算爲 false,不然爲 true
    • 字符串 若是是空字符串 '' 被計算爲 false,不然爲 true

     

    if ([0]) {
      // true
      // 一個數組就是一個對象,對象被計算爲 true
    }

     

  • 使用快捷方式。

     

    // bad
    if (name !== '') {
      // ...stuff...
    }
    
    // good
    if (name) {
      // ...stuff...
    }
    
    // bad
    if (collection.length > 0) {
      // ...stuff...
    }
    
    // good
    if (collection.length) {
      // ...stuff...
    }

     

  • 瞭解更多信息在 Truth Equality and JavaScript by Angus Croll.

  • 使用大括號包裹全部的多行代碼塊。

     

    // bad
    if (test)
      return false;
    
    // good
    if (test) return false;
    
    // good
    if (test) {
      return false;
    }
    
    // bad
    function () { return false; }
    
    // good
    function () {
      return false;
    }

     

  • 若是經過 if 和 else 使用多行代碼塊,把 else 放在 if 代碼塊關閉括號的同一行。

     

    // bad
    if (test) {
      thing1();
      thing2();
    }
    else {
      thing3();
    }
    
    // good
    if (test) {
      thing1();
      thing2();
    } else {
      thing3();
    }

     

⬆ 回到頂部

註釋

  • 使用 /** ... */ 做爲多行註釋。包含描述、指定全部參數和返回值的類型和值。

     

    // bad
    // make() returns a new element
    // based on the passed in tag name
    //
    // @param {String} tag
    // @return {Element} element
    function make(tag) {
    
      // ...stuff...
    
      return element;
    }
    
    // good
    /**
     * make() returns a new element
     * based on the passed in tag name
     *
     * @param {String} tag
     * @return {Element} element
     */
    function make(tag) {
    
      // ...stuff...
    
      return element;
    }

     

  • 使用 // 做爲單行註釋。在評論對象上面另起一行使用單行註釋。在註釋前插入空行。

     

    // bad
    var active = true;  // is current tab
    
    // good
    // is current tab
    var active = true;
    
    // bad
    function getType() {
      console.log('fetching type...');
      // set the default type to 'no type'
      var type = this.type || 'no type';
    
      return type;
    }
    
    // good
    function getType() {
      console.log('fetching type...');
    
      // set the default type to 'no type'
      var type = this.type || 'no type';
    
      return type;
    }

     

  • 給註釋增長 FIXME 或 TODO 的前綴能夠幫助其餘開發者快速瞭解這是一個須要複查的問題,或是給須要實現的功能提供一個解決方式。這將有別於常見的註釋,由於它們是可操做的。使用 FIXME -- need to figure this out 或者 TODO -- need to implement

  • 使用 // FIXME: 標註問題。

     

    function Calculator() {
    
      // FIXME: shouldn't use a global here
      total = 0;
    
      return this;
    }

     

  • 使用 // TODO: 標註問題的解決方式。

     

    function Calculator() {
    
      // TODO: total should be configurable by an options param
      this.total = 0;
    
      return this;
    }

     

⬆ 回到頂部

空白

  • 使用 4 個空格做爲縮進(注:原指南建議的是2個空格)。

     

    // bad
    function () {
    ∙∙∙∙var name;
    }
    
    // bad
    function () {
    ∙var name;
    }
    
    // good
    function () {
    ∙∙∙∙var name;
    }

     

  • 在大括號前放一個空格。

     

    // bad
    function test(){
      console.log('test');
    }
    
    // good
    function test() {
      console.log('test');
    }
    
    // bad
    dog.set('attr',{
      age: '1 year',
      breed: 'Bernese Mountain Dog'
    });
    
    // good
    dog.set('attr', {
      age: '1 year',
      breed: 'Bernese Mountain Dog'
    });

     

  • 在控制語句(ifwhile 等)的小括號前放一個空格。在函數調用及聲明中,不在函數的參數列表前加空格。

     

    // bad
    if(isJedi) {
      fight ();
    }
    
    // good
    if (isJedi) {
      fight();
    }
    
    // bad
    function fight () {
      console.log ('Swooosh!');
    }
    
    // good
    function fight() {
      console.log('Swooosh!');
    }

     

  • 使用空格把運算符隔開。

     

    // bad
    var x=y+5;
    
    // good
    var x = y + 5;

     

  • 在文件末尾插入一個空行。

     

    // bad
    (function (global) {
      // ...stuff...
    })(this);
     
    // bad
    (function (global) {
      // ...stuff...
    })(this);↵
    ↵
     
    // good
    (function (global) {
      // ...stuff...
    })(this);↵

     

  • 在使用長方法鏈時進行縮進。使用前面的點 . 強調這是方法調用而不是新語句。

     

    // bad
    $('#items').find('.selected').highlight().end().find('.open').updateCount();
    
    // bad
    $('#items').
      find('.selected').
        highlight().
        end().
      find('.open').
        updateCount();
    
    // good
    $('#items')
      .find('.selected')
        .highlight()
        .end()
      .find('.open')
        .updateCount();
    
    // bad
    var leds = stage.selectAll('.led').data(data).enter().append('svg:svg').classed('led', true)
        .attr('width', (radius + margin) * 2).append('svg:g')
        .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')')
        .call(tron.led);
    
    // good
    var leds = stage.selectAll('.led')
        .data(data)
      .enter().append('svg:svg')
        .classed('led', true)
        .attr('width', (radius + margin) * 2)
      .append('svg:g')
        .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')')
        .call(tron.led);

     

  • 在塊末和新語句前插入空行。

     

    // bad
    if (foo) {
      return bar;
    }
    return baz;
    
    // good
    if (foo) {
      return bar;
    }
    
    return baz;
    
    // bad
    var obj = {
      foo: function () {
      },
      bar: function () {
      }
    };
    return obj;
    
    // good
    var obj = {
      foo: function () {
      },
    
      bar: function () {
      }
    };
    
    return obj;

     

逗號

  • 行首逗號: 不須要

     

    // bad
    var story = [
        once
      , upon
      , aTime
    ];
    
    // good
    var story = [
      once,
      upon,
      aTime
    ];
    
    // bad
    var hero = {
        firstName: 'Bob'
      , lastName: 'Parr'
      , heroName: 'Mr. Incredible'
      , superPower: 'strength'
    };
    
    // good
    var hero = {
      firstName: 'Bob',
      lastName: 'Parr',
      heroName: 'Mr. Incredible',
      superPower: 'strength'
    };

     

  • 額外的行末逗號:不須要。這樣作會在 IE6/7 和 IE9 怪異模式下引發問題。一樣,多餘的逗號在某些 ES3 的實現裏會增長數組的長度。在 ES5 中已經澄清了 (source):

Edition 5 clarifies the fact that a trailing comma at the end of an ArrayInitialiser does not add to the length of the array. This is not a semantic change from Edition 3 but some implementations may have previously misinterpreted this.

// bad
var hero = {
  firstName: 'Kevin',
  lastName: 'Flynn',
};

var heroes = [
  'Batman',
  'Superman',
];

// good
var hero = {
  firstName: 'Kevin',
  lastName: 'Flynn'
};

var heroes = [
  'Batman',
  'Superman'
];
 

分號

  • 使用分號。

     

    // bad
    (function () {
      var name = 'Skywalker'
      return name
    })()
    
    // good
    (function () {
      var name = 'Skywalker';
      return name;
    })();
    
    // good (防止函數在兩個 IIFE 合併時被當成一個參數
    ;(function () {
      var name = 'Skywalker';
      return name;
    })();

     

    瞭解更多.

類型轉換

  • 在語句開始時執行類型轉換。

  • 字符串:

     

    //  => this.reviewScore = 9;
    
    // bad
    var totalScore = this.reviewScore + '';
    
    // good
    var totalScore = '' + this.reviewScore;
    
    // bad
    var totalScore = '' + this.reviewScore + ' total score';
    
    // good
    var totalScore = this.reviewScore + ' total score';

     

  • 使用 parseInt 轉換數字時老是帶上類型轉換的基數。

     

    var inputValue = '4';
    
    // bad
    var val = new Number(inputValue);
    
    // bad
    var val = +inputValue;
    
    // bad
    var val = inputValue >> 0;
    
    // bad
    var val = parseInt(inputValue);
    
    // good
    var val = Number(inputValue);
    
    // good
    var val = parseInt(inputValue, 10);

     

  • 若是由於某些緣由 parseInt 成爲你所作的事的瓶頸而須要使用位操做解決性能問題時,留個註釋說清楚緣由和你的目的。

     

    // good
    /**
     * parseInt was the reason my code was slow.
     * Bitshifting the String to coerce it to a
     * Number made it a lot faster.
     */
    var val = inputValue >> 0;

     

  • 注: 當心使用位操做運算符。數字會被當成 64 位值,可是位操做運算符老是返回 32 位的整數(source)。位操做處理大於 32 位的整數值時還會致使意料以外的行爲。討論。最大的 32 位整數是 2,147,483,647:

     

    2147483647 >> 0 //=> 2147483647
    2147483648 >> 0 //=> -2147483648
    2147483649 >> 0 //=> -2147483647

     

  • 布爾:

     

    var age = 0;
    
    // bad
    var hasAge = new Boolean(age);
    
    // good
    var hasAge = Boolean(age);
    
    // good
    var hasAge = !!age;

     

命名規則

  • 避免單字母命名。命名應具有描述性。

     

    // bad
    function q() {
      // ...stuff...
    }
    
    // good
    function query() {
      // ..stuff..
    }

     

  • 使用駝峯式命名對象、函數和實例。

     

    // bad
    var OBJEcttsssss = {};
    var this_is_my_object = {};
    var o = {};
    function c() {}
    
    // good
    var thisIsMyObject = {};
    function thisIsMyFunction() {}

     

  • 使用帕斯卡式命名構造函數或類。

     

    // bad
    function user(options) {
      this.name = options.name;
    }
    
    var bad = new user({
      name: 'nope'
    });
    
    // good
    function User(options) {
      this.name = options.name;
    }
    
    var good = new User({
      name: 'yup'
    });

     

  • 不要使用下劃線前/後綴。

爲何?JavaScript 並無私有屬性或私有方法的概念。雖然使用下劃線是表示「私有」的一種共識,但實際上這些屬性是徹底公開的,它自己就是你公共接口的一部分。這種習慣或許會致使開發者錯誤的認爲改動它不會形成破壞或者不須要去測試。長話短說:若是你想要某處爲「私有」,它必須不能是顯式提出的。

// bad
this.__firstName__ = 'Panda';
this.firstName_ = 'Panda';
this._firstName = 'Panda';

// good
this.firstName = 'Panda';
 
  • 不要保存 this 的引用。使用 Function#bind。

     

    // bad
    function () {
      var self = this;
      return function () {
        console.log(self);
      };
    }
    
    // bad
    function () {
      var that = this;
      return function () {
        console.log(that);
      };
    }
    
    // bad
    function () {
      var _this = this;
      return function () {
        console.log(_this);
      };
    }
    
    // good
    function () {
      return function () {
        console.log(this);
      }.bind(this);
    }

     

  • 給函數命名。這在作堆棧軌跡時頗有幫助。

     

    // bad
    var log = function (msg) {
      console.log(msg);
    };
    
    // good
    var log = function log(msg) {
      console.log(msg);
    };

     

  • 注: IE8 及如下版本對命名函數表達式的處理有些怪異。瞭解更多信息到 http://kangax.github.io/nfe/

  • 若是你的文件導出一個類,你的文件名應該與類名徹底相同。

     

    // file contents
    class CheckBox {
      // ...
    }
    module.exports = CheckBox;
    
    // in some other file
    // bad
    var CheckBox = require('./checkBox');
    
    // bad
    var CheckBox = require('./check_box');
    
    // good
    var CheckBox = require('./CheckBox');

     

存取器

  • 屬性的存取函數不是必須的。

  • 若是你須要存取函數時使用 getVal() 和 setVal('hello')

     

    // bad
    dragon.age();
    
    // good
    dragon.getAge();
    
    // bad
    dragon.age(25);
    
    // good
    dragon.setAge(25);

     

  • 若是屬性是布爾值,使用 isVal() 或 hasVal()

     

    // bad
    if (!dragon.age()) {
      return false;
    }
    
    // good
    if (!dragon.hasAge()) {
      return false;
    }

     

  • 建立 get() 和 set() 函數是能夠的,但要保持一致。

     

    function Jedi(options) {
      options || (options = {});
      var lightsaber = options.lightsaber || 'blue';
      this.set('lightsaber', lightsaber);
    }
    
    Jedi.prototype.set = function set(key, val) {
      this[key] = val;
    };
    
    Jedi.prototype.get = function get(key) {
      return this[key];
    };

     

構造函數

  • 給對象原型分配方法,而不是使用一個新對象覆蓋原型。覆蓋原型將致使繼承出現問題:重設原型將覆蓋原有原型!

     

    function Jedi() {
      console.log('new jedi');
    }
    
    // bad
    Jedi.prototype = {
      fight: function fight() {
        console.log('fighting');
      },
    
      block: function block() {
        console.log('blocking');
      }
    };
    
    // good
    Jedi.prototype.fight = function fight() {
      console.log('fighting');
    };
    
    Jedi.prototype.block = function block() {
      console.log('blocking');
    };

     

  • 方法能夠返回 this 來實現方法鏈式使用。

     

    // bad
    Jedi.prototype.jump = function jump() {
      this.jumping = true;
      return true;
    };
    
    Jedi.prototype.setHeight = function setHeight(height) {
      this.height = height;
    };
    
    var luke = new Jedi();
    luke.jump(); // => true
    luke.setHeight(20); // => undefined
    
    // good
    Jedi.prototype.jump = function jump() {
      this.jumping = true;
      return this;
    };
    
    Jedi.prototype.setHeight = function setHeight(height) {
      this.height = height;
      return this;
    };
    
    var luke = new Jedi();
    
    luke.jump()
      .setHeight(20);

     

  • 寫一個自定義的 toString() 方法是能夠的,可是確保它能夠正常工做且不會產生反作用。

     

    function Jedi(options) {
      options || (options = {});
      this.name = options.name || 'no name';
    }
    
    Jedi.prototype.getName = function getName() {
      return this.name;
    };
    
    Jedi.prototype.toString = function toString() {
      return 'Jedi - ' + this.getName();
    };

     

事件

  • 當給事件附加數據時(不管是 DOM 事件仍是私有事件),傳入一個哈希而不是原始值。這樣可讓後面的貢獻者增長更多數據到事件數據而無需找出並更新事件的每個處理器。例如,很差的寫法:

     

    // bad
    $(this).trigger('listingUpdated', listing.id);
    
    ...
    
    $(this).on('listingUpdated', function (e, listingId) {
      // do something with listingId
    });

     

    更好的寫法:

     

    // good
    $(this).trigger('listingUpdated', { listingId : listing.id });
    
    ...
    
    $(this).on('listingUpdated', function (e, data) {
      // do something with data.listingId
    });

     

模塊

  • 模塊應該以 ! 開始。這樣確保了當一個很差的模塊忘記包含最後的分號時,在合併代碼到生產環境後不會產生錯誤。詳細說明

  • 文件應該以駝峯式命名,並放在同名的文件夾裏,且與導出的名字一致。

  • 增長一個名爲 noConflict() 的方法來設置導出的模塊爲前一個版本並返回它。

  • 永遠在模塊頂部聲明 'use strict';

     

    // fancyInput/fancyInput.js
    
    !function (global) {
      'use strict';
    
      var previousFancyInput = global.FancyInput;
    
      function FancyInput(options) {
        this.options = options || {};
      }
    
      FancyInput.noConflict = function noConflict() {
        global.FancyInput = previousFancyInput;
        return FancyInput;
      };
    
      global.FancyInput = FancyInput;
    }(this);

     

jQuery

  • 使用 $ 做爲存儲 jQuery 對象的變量名前綴。

     

    // bad
    var sidebar = $('.sidebar');
    
    // good
    var $sidebar = $('.sidebar');

     

  • 緩存 jQuery 查詢。

     

    // bad
    function setSidebar() {
      $('.sidebar').hide();
    
      // ...stuff...
    
      $('.sidebar').css({
        'background-color': 'pink'
      });
    }
    
    // good
    function setSidebar() {
      var $sidebar = $('.sidebar');
      $sidebar.hide();
    
      // ...stuff...
    
      $sidebar.css({
        'background-color': 'pink'
      });
    }

     

  • 對 DOM 查詢使用層疊 $('.sidebar ul') 或 父元素 > 子元素 $('.sidebar > ul')。 jsPerf

  • 對有做用域的 jQuery 對象查詢使用 find

     

    // bad
    $('ul', '.sidebar').hide();
    
    // bad
    $('.sidebar').find('ul').hide();
    
    // good
    $('.sidebar ul').hide();
    
    // good
    $('.sidebar > ul').hide();
    
    // good
    $sidebar.find('ul').hide();

     

ECMAScript 5 兼容性

 

關於ES6版本的指南,後續將根據狀況擇期推廣。

ES6 英文版:https://github.com/airbnb/javascript

相關文章
相關標籤/搜索