JavaScript_Style_Guide

JavaScript Style Guide

用更合理的方式寫 JavaScript

<a name="table-of-contents">目錄</a>

  1. 類型
  2. 對(duì)象
  3. 數(shù)組
  4. 字符串
  5. 函數(shù)
  6. 屬性
  7. 變量
  8. 提升
  9. 比較運(yùn)算符 & 等號(hào)
  10. 注釋
  11. 空白
  12. 逗號(hào)
  13. 分號(hào)
  14. 類型轉(zhuǎn)化
  15. 命名規(guī)則
  16. 存取器
  17. 構(gòu)造函數(shù)
  18. 事件
  19. 模塊
  20. jQuery
  21. ECMAScript 5 兼容性
  22. 測(cè)試

<a name="types">類型</a>

  • 原始值: 存取直接作用于它自身。

    • string
    • number
    • boolean
    • null
    • undefined
    var foo = 1;
    var bar = foo;
    
    bar = 9;
    
    console.log(foo, bar); // => 1, 9
    
  • 復(fù)雜類型: 存取時(shí)作用于它自身值的引用。

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

? 回到頂部

<a name="objects">對(duì)象</a>

  • 使用直接量創(chuàng)建對(duì)象。

    // bad
    var item = new Object();
    
    // good
    var item = {};
    
  • 不要使用保留字作為鍵名,它們?cè)?IE8 下不工作。更多信息

    // 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'
    };
    

? 回到頂部

<a name="arrays">數(shù)組</a>

  • 使用直接量創(chuàng)建數(shù)組。

    // bad
    var items = new Array();
    
    // good
    var items = [];
    
  • 向數(shù)組增加元素時(shí)使用 Array#push 來替代直接賦值。

    var someStack = [];
    
    
    // bad
    someStack[someStack.length] = 'abracadabra';
    
    // good
    someStack.push('abracadabra');
    
  • 當(dāng)你需要拷貝數(shù)組時(shí),使用 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 將類數(shù)組對(duì)象轉(zhuǎn)換成數(shù)組。

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

? 回到頂部

<a name="strings">字符串</a>

  • 使用單引號(hào) '' 包裹字符串。

    // bad
    var name = "Bob Parr";
    
    // good
    var name = 'Bob Parr';
    
    // bad
    var fullName = "Bob " + this.lastName;
    
    // good
    var fullName = 'Bob ' + this.lastName;
    
  • 超過 100 個(gè)字符的字符串應(yīng)該使用連接符寫成多行。

  • 注:若過度使用,通過連接符連接的長字符串可能會(huì)影響性能。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>';
    }
    

? 回到頂部

<a name="functions">函數(shù)</a>

  • 函數(shù)表達(dá)式:

    // 匿名函數(shù)表達(dá)式
    var anonymous = function() {
      return true;
    };
    
    // 命名函數(shù)表達(dá)式
    var named = function named() {
      return true;
    };
    
    // 立即調(diào)用的函數(shù)表達(dá)式(IIFE)
    (function () {
      console.log('Welcome to the Internet. Please follow me.');
    }());
    
  • 永遠(yuǎn)不要在一個(gè)非函數(shù)代碼塊(if、while 等)中聲明一個(gè)函數(shù),把那個(gè)函數(shù)賦給一個(gè)變量。瀏覽器允許你這么做,但它們的解析表現(xiàn)不一致。

  • 注: ECMA-262 把 定義為一組語句。函數(shù)聲明不是語句。閱讀對(duì) ECMA-262 這個(gè)問題的說明

    // bad
    if (currentUser) {
      function test() {
        console.log('Nope.');
      }
    }
    
    // good
    var test;
    if (currentUser) {
      test = function test() {
        console.log('Yup.');
      };
    }
    
  • 永遠(yuǎn)不要把參數(shù)命名為 arguments。這將取代函數(shù)作用域內(nèi)的 arguments 對(duì)象。

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

? 回到頂部

<a name="properties">屬性</a>

  • 使用 . 來訪問對(duì)象的屬性。

    var luke = {
      jedi: true,
      age: 28
    };
    
    // bad
    var isJedi = luke['jedi'];
    
    // good
    var isJedi = luke.jedi;
    
  • 當(dāng)通過變量訪問屬性時(shí)使用中括號(hào) []

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

? 回到頂部

<a name="variables">變量</a>

  • 總是使用 var 來聲明變量。不這么做將導(dǎo)致產(chǎn)生全局變量。我們要避免污染全局命名空間。

    // bad
    superPower = new SuperPower();
    
    // good
    var superPower = new SuperPower();
    
  • 使用 var 聲明每一個(gè)變量。
    這樣做的好處是增加新變量將變的更加容易,而且你永遠(yuǎn)不用再擔(dān)心調(diào)換錯(cuò) ;,

    // bad
    var items = getItems(),
        goSportsTeam = true,
        dragonball = 'z';
    
    // bad
    // (跟上面的代碼比較一下,看看哪里錯(cuò)了)
    var items = getItems(),
        goSportsTeam = true;
        dragonball = 'z';
    
    // good
    var items = getItems();
    var goSportsTeam = true;
    var dragonball = 'z';
    
  • 最后再聲明未賦值的變量。當(dāng)你需要引用前面的變量賦值時(shí)這將變的很有用。

    // 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;
    

? 回到頂部

<a name="hoisting">提升</a>

  • 變量聲明會(huì)提升至作用域頂部,但賦值不會(huì)。

    // 我們知道這樣不能正常工作(假設(shè)這里沒有名為 notDefined 的全局變量)
    function example() {
      console.log(notDefined); // => throws a ReferenceError
    }
    
    // 但由于變量聲明提升的原因,在一個(gè)變量引用后再創(chuàng)建它的變量聲明將可以正常工作。
    // 注:變量賦值為 `true` 不會(huì)提升。
    function example() {
      console.log(declaredButNotAssigned); // => undefined
      var declaredButNotAssigned = true;
    }
    
    // 解釋器會(huì)把變量聲明提升到作用域頂部,意味著我們的例子將被重寫成:
    function example() {
      var declaredButNotAssigned;
      console.log(declaredButNotAssigned); // => undefined
      declaredButNotAssigned = true;
    }
    
  • 匿名函數(shù)表達(dá)式會(huì)提升它們的變量名,但不會(huì)提升函數(shù)的賦值。

    function example() {
      console.log(anonymous); // => undefined
    
      anonymous(); // => TypeError anonymous is not a function
    
      var anonymous = function () {
        console.log('anonymous function expression');
      };
    }
    
  • 命名函數(shù)表達(dá)式會(huì)提升變量名,但不會(huì)提升函數(shù)名或函數(shù)體。

    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');
      };
    }
    
    // 當(dāng)函數(shù)名跟變量名一樣時(shí),表現(xiàn)也是如此。
    function example() {
      console.log(named); // => undefined
    
      named(); // => TypeError named is not a function
    
      var named = function named() {
        console.log('named');
      }
    }
    
  • 函數(shù)聲明提升它們的名字和函數(shù)體。

    function example() {
      superPower(); // => Flying
    
      function superPower() {
        console.log('Flying');
      }
    }
    
  • 了解更多信息在 JavaScript Scoping & Hoisting by Ben Cherry.

? 回到頂部

<a name="comparison-operators--equality">比較運(yùn)算符 & 等號(hào)</a>

  • 優(yōu)先使用 ===!== 而不是 ==!=.

  • 條件表達(dá)式例如 if 語句通過抽象方法 ToBoolean 強(qiáng)制計(jì)算它們的表達(dá)式并且總是遵守下面的規(guī)則:

    • 對(duì)象 被計(jì)算為 true
    • Undefined 被計(jì)算為 false
    • Null 被計(jì)算為 false
    • 布爾值 被計(jì)算為 布爾的值
    • 數(shù)字 如果是 +0、-0 或 NaN 被計(jì)算為 false,否則為 true
    • 字符串 如果是空字符串 '' 被計(jì)算為 false,否則為 true
    if ([0]) {
      // true
      // 一個(gè)數(shù)組就是一個(gè)對(duì)象,對(duì)象被計(jì)算為 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.

? 回到頂部

<a name="blocks">塊</a>

  • 使用大括號(hào)包裹所有的多行代碼塊。

    // bad
    if (test)
      return false;
    
    // good
    if (test) return false;
    
    // good
    if (test) {
      return false;
    }
    
    // bad
    function () { return false; }
    
    // good
    function () {
      return false;
    }
    
  • 如果通過 ifelse 使用多行代碼塊,把 else 放在 if 代碼塊關(guān)閉括號(hào)的同一行。

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

? 回到頂部

<a name="comments">注釋</a>

  • 使用 /** ... */ 作為多行注釋。包含描述、指定所有參數(shù)和返回值的類型和值。

    // 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;
    }
    
  • 使用 // 作為單行注釋。在評(píng)論對(duì)象上面另起一行使用單行注釋。在注釋前插入空行。

    // 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;
    }
    
  • 給注釋增加 FIXMETODO 的前綴可以幫助其他開發(fā)者快速了解這是一個(gè)需要復(fù)查的問題,或是給需要實(shí)現(xiàn)的功能提供一個(gè)解決方式。這將有別于常見的注釋,因?yàn)樗鼈兪强刹僮鞯摹J褂?FIXME -- need to figure this out 或者 TODO -- need to implement

  • 使用 // FIXME: 標(biāo)注問題。

    function Calculator() {
    
      // FIXME: shouldn't use a global here
      total = 0;
    
      return this;
    }
    
  • 使用 // TODO: 標(biāo)注問題的解決方式。

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

? 回到頂部

<a name="whitespace">空白</a>

  • 使用 2 個(gè)或 4 個(gè)空格作為縮進(jìn)(請(qǐng)保持統(tǒng)一)。

    // bad
    function () {
    ?var name;
    }
    
    // good
    function () {
    ??var name;
    }
    
    // good
    function () {
    ????var name;
    }
    
  • 在大括號(hào)前放一個(gè)空格。

    // 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 等)的小括號(hào)前放一個(gè)空格。在函數(shù)調(diào)用及聲明中,不在函數(shù)的參數(shù)列表前加空格。

    // bad
    if(isJedi) {
      fight ();
    }
    
    // good
    if (isJedi) {
      fight();
    }
    
    // bad
    function fight () {
      console.log ('Swooosh!');
    }
    
    // good
    function fight() {
      console.log('Swooosh!');
    }
    
  • 使用空格把運(yùn)算符隔開。

    // bad
    var x=y+5;
    
    // good
    var x = y + 5;
    
  • 在文件末尾插入一個(gè)空行。

    // bad
    (function (global) {
      // ...stuff...
    })(this);
    
    // bad
    (function (global) {
      // ...stuff...
    })(this);?
    ?
    
    // good
    (function (global) {
      // ...stuff...
    })(this);?
    
  • 在使用長方法鏈時(shí)進(jìn)行縮進(jìn)。使用前面的點(diǎn) . 強(qiáng)調(diào)這是方法調(diào)用而不是新語句。

    // 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;
    

? 回到頂部

<a name="commas">逗號(hào)</a>

  • 行首逗號(hào): 不需要

    // 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'
    };
    

? 回到頂部

<a name="semicolons">分號(hào)</a>

  • 使用分號(hào)。

    // bad
    (function () {
      var name = 'Skywalker'
      return name
    })()
    
    // good
    (function () {
      var name = 'Skywalker';
      return name;
    })();
    
    // good (防止函數(shù)在兩個(gè) IIFE 合并時(shí)被當(dāng)成一個(gè)參數(shù)
    ;(function () {
      var name = 'Skywalker';
      return name;
    })();
    

    了解更多.

? 回到頂部

<a name="type-casting--coercion">類型轉(zhuǎn)換</a>

  • 在語句開始時(shí)執(zhí)行類型轉(zhuǎn)換。

  • 字符串:

    //  => 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 轉(zhuǎn)換數(shù)字時(shí)總是帶上類型轉(zhuǎn)換的基數(shù)。

    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);
    
  • 如果因?yàn)槟承┰?parseInt 成為你所做的事的瓶頸而需要使用位操作解決性能問題時(shí),留個(gè)注釋說清楚原因和你的目的。

    // 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;
    
  • 注: 小心使用位操作運(yùn)算符。數(shù)字會(huì)被當(dāng)成 64 位值,但是位操作運(yùn)算符總是返回 32 位的整數(shù)(source)。位操作處理大于 32 位的整數(shù)值時(shí)還會(huì)導(dǎo)致意料之外的行為。討論。最大的 32 位整數(shù)是 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;
    

? 回到頂部

<a name="naming-conventions">命名規(guī)則</a>

  • 避免單字母命名。命名應(yīng)具備描述性。

    // bad
    function q() {
      // ...stuff...
    }
    
    // good
    function query() {
      // ..stuff..
    }
    
  • 使用駝峰式命名對(duì)象、函數(shù)和實(shí)例。

    // bad
    var OBJEcttsssss = {};
    var this_is_my_object = {};
    var o = {};
    function c() {}
    
    // good
    var thisIsMyObject = {};
    function thisIsMyFunction() {}
    
  • 使用帕斯卡式命名構(gòu)造函數(shù)或類。

    // 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 并沒有私有屬性或私有方法的概念。雖然使用下劃線是表示「私有」的一種共識(shí),但實(shí)際上這些屬性是完全公開的,它本身就是你公共接口的一部分。這種習(xí)慣或許會(huì)導(dǎo)致開發(fā)者錯(cuò)誤的認(rèn)為改動(dòng)它不會(huì)造成破壞或者不需要去測(cè)試。長話短說:如果你想要某處為「私有」,它必須不能是顯式提出的。

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

// good
this.firstName = 'Panda';
```
  • 給函數(shù)命名。這在做堆棧軌跡時(shí)很有幫助。

    // bad
    var log = function (msg) {
      console.log(msg);
    };
    
    // good
    var log = function log(msg) {
      console.log(msg);
    };
    
  • 注: IE8 及以下版本對(duì)命名函數(shù)表達(dá)式的處理有些怪異。了解更多信息到 http://kangax.github.io/nfe/

  • 如果你的文件導(dǎo)出一個(gè)類,你的文件名應(yīng)該與類名完全相同。

    // 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');
    

? 回到頂部

<a name="accessors">存取器</a>

  • 屬性的存取函數(shù)不是必須的。

  • 如果你需要存取函數(shù)時(shí)使用 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;
    }
    
  • 創(chuàng)建 get() 和 set() 函數(shù)是可以的,但要保持一致。

    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];
    };
    

? 回到頂部

<a name="constructors">構(gòu)造函數(shù)</a>

  • 給對(duì)象原型分配方法,而不是使用一個(gè)新對(duì)象覆蓋原型。覆蓋原型將導(dǎo)致繼承出現(xiàn)問題:重設(shè)原型將覆蓋原有原型!

    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 來實(shí)現(xiàn)方法鏈?zhǔn)绞褂谩?/p>

    // 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);
    
  • 寫一個(gè)自定義的 toString() 方法是可以的,但是確保它可以正常工作且不會(huì)產(chǎn)生副作用。

    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();
    };
    

? 回到頂部

<a name="events">事件</a>

  • 當(dāng)給事件附加數(shù)據(jù)時(shí)(無論是 DOM 事件還是私有事件),傳入一個(gè)哈希而不是原始值。這樣可以讓后面的貢獻(xiàn)者增加更多數(shù)據(jù)到事件數(shù)據(jù)而無需找出并更新事件的每一個(gè)處理器。例如,不好的寫法:

    // 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
    });
    

? 回到頂部

<a name="modules">模塊</a>

  • 模塊應(yīng)該以 ! 開始。這樣確保了當(dāng)一個(gè)不好的模塊忘記包含最后的分號(hào)時(shí),在合并代碼到生產(chǎn)環(huán)境后不會(huì)產(chǎn)生錯(cuò)誤。詳細(xì)說明

  • 文件應(yīng)該以駝峰式命名,并放在同名的文件夾里,且與導(dǎo)出的名字一致。

  • 增加一個(gè)名為 noConflict() 的方法來設(shè)置導(dǎo)出的模塊為前一個(gè)版本并返回它。

  • 永遠(yuǎn)在模塊頂部聲明 '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);
    

? 回到頂部

<a name="jquery">jQuery</a>

  • 使用 $ 作為存儲(chǔ) jQuery 對(duì)象的變量名前綴。

    // 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'
      });
    }
    
  • 對(duì) DOM 查詢使用層疊 $('.sidebar ul') 或 父元素 > 子元素 $('.sidebar > ul')jsPerf

  • 對(duì)有作用域的 jQuery 對(duì)象查詢使用 find

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

? 回到頂部

<a name="ecmascript-5-compatibility">ECMAScript 5 兼容性</a>

? 回到頂部

<a name="testing">測(cè)試</a>

  • Yup.

    function () {
      return true;
    }
    

? 回到頂部

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • (a fork of Airbnb's Javascript Style Guide) Strikingly ES...
    飄零_zyw閱讀 1,190評(píng)論 1 2
  • JavaScript規(guī)范 <a name='TOC'>內(nèi)容列表</a> 類型 對(duì)象 數(shù)組 字符串 函數(shù) 屬性 變量...
    帶三本書閱讀 506評(píng)論 0 1
  • 單例模式 適用場(chǎng)景:可能會(huì)在場(chǎng)景中使用到對(duì)象,但只有一個(gè)實(shí)例,加載時(shí)并不主動(dòng)創(chuàng)建,需要時(shí)才創(chuàng)建 最常見的單例模式,...
    Obeing閱讀 2,093評(píng)論 1 10
  • 我是一位高三的學(xué)生啦 我們學(xué)校有個(gè)很高也很陽光的男生,恰巧是我喜歡的類型,我便偷偷的打聽關(guān)于他的一切事情 我明白身...
    林可姆兒醬閱讀 192評(píng)論 0 0
  • 聽媽媽講你過去的事情 46)“卑鄙”的來由(九歲) 媽媽在日常生活中,一直叫寶寶卑鄙,無論寫在文章里,或者口頭上,...
    上林葉閱讀 611評(píng)論 8 3