Airbnb JavaScript 編碼風格指南(2018年最新版)

Airbnb JavaScript 編碼風格指南(2018年最新版)

訪問此原文地址: http://galaxyteam.pub/didi-fe...
另外歡迎訪問咱們維護的 https://www.threejs.online 中文站 (歡迎Star!)

本文譯者:滴滴出行上海前端(FE)團隊楊永樂同窗javascript

類型

  1. 基本類型:直接存取css

    • string
    • number
    • boolean
    • null
    • undefined
    • symbol
    const foo = 1;
    let bar = foo;
    
    bar = 9;
    
    console.log(foo, bar); // => 1, 9
    • symbol 類型不能徹底polyfilled,因此請謹慎使用
  2. 複雜類型: 經過引用的方式存取html

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

引用

  1. 使用const申明引用類型,避免使用var。eslint 設置:prefer-const,no-const-assign前端

    爲何?這能確保你沒法對引用從新賦值,也不會致使出現 bug 或難以理解。
    // bad
    var a = 1;
    var b = 2;
    
    // good
    const a = 1;
    const b = 2;
  2. 若是必須對引用類型從新賦值,使用let而非var。eslint設置:no-var jscs: disallowVarjava

    爲何?相比於 var函數做用域, let塊級做用域更容易理解
    // bad
    var count = 1;
    if (true) {
      count += 1;
    }
    
    // good, use the let.
    let count = 1;
    if (true) {
      count += 1;
    }
  3. 注意letconst都是塊級做用域node

    // const and let only exist in the blocks they are defined in.
    {
      let a = 1;
      const b = 1;
    }
    console.log(a); // ReferenceError
    console.log(b); // ReferenceError

對象

  1. 使用字面值建立對象。eslint: no-new-objectwebpack

    // bad
    const item = new Object();
    
    // good
    const item = {};
  2. 建立對象的動態屬性時,使用計算屬性git

    爲何?這樣能夠在一個地方定義對象全部的屬性
    function getKey(k) {
      return `a key named ${k}`;
    }
    
    // bad
    const obj = {
      id: 5,
      name: 'San Francisco',
    };
    obj[getKey('enabled')] = true;
    
    // good
    const obj = {
      id: 5,
[getKey('enabled')]: true,
};
```
  1. 使用對象方法的簡寫形式。 eslint: object-shorthand jscs: requireEnhancedObjectLiteralses6

    爲何?方法定義簡潔清晰
    // bad
    const atom = {
      value: 1,
    
      addValue: function (value) {
        return atom.value + value;
      },
    };
    
    // good
    const atom = {
      value: 1,
    
      addValue(value) {
        return atom.value + value;
      },
    };
  2. 使用屬性值簡寫形式。eslint: object-shorthand jscs: [requireEnhancedObjectLiterals]github

    爲何?書寫更加簡潔,更有描述性。
    const lukeSkywalker = 'Luke Skywalker';
    
    // bad
    const obj = {
      lukeSkywalker: lukeSkywalker,
    };
    
    // good
    const obj = {
      lukeSkywalker,
    };
  3. 對象聲明時分類簡寫和非簡寫的屬性名。

    爲何?更清晰的瞭解哪些屬性是簡寫的。
    const anakinSkywalker = 'Anakin Skywalker';
    const lukeSkywalker = 'Luke Skywalker';
    
    // bad
    const obj = {
      episodeOne: 1,
      twoJediWalkIntoACantina: 2,
      lukeSkywalker,
      episodeThree: 3,
      mayTheFourth: 4,
      anakinSkywalker,
    };
    
    // good
    const obj = {
      lukeSkywalker,
      anakinSkywalker,
      episodeOne: 1,
      twoJediWalkIntoACantina: 2,
      episodeThree: 3,
      mayTheFourth: 4,
    };
  4. 只有對那些不合法的屬性名標識符添加引號。eslint: quote-props jscs: disallowQuotedKeysInObjects

    爲何?對象屬性更直觀,可讀性強。可以代碼高亮顯示,同時對於大多數的js引擎更容易優化代碼。
    // bad
    const bad = {
      'foo': 3,
      'bar': 4,
      'data-blah': 5,
    };
    
    // good
    const good = {
      foo: 3,
      bar: 4,
      'data-blah': 5,
    };
  5. 不要直接使用Object.prototype上的方法,例如hasOwnProperty, propertyIsEnumerable, 和 isPrototypeOf

    爲何?這些方法可能受對象的其餘屬性影響。例如 { hasOwnProperty: false } 或者 對象多是null( Object.create(null))
    // bad
    console.log(object.hasOwnProperty(key));
    
    const object = Object.create(null);
    obj.hasOwnProperty(key) // Uncaught TypeError: obj.hasOwnProperty is not a function
    
    // good
    console.log(Object.prototype.hasOwnProperty.call(object, key));
    
    // best
    const has = Object.prototype.hasOwnProperty; // cache the lookup once, in module scope.
    /* or */
    import has from 'has'; // https://www.npmjs.com/package/has
    // ...
    console.log(has.call(object, key));
  6. 淺拷貝對象時推薦使用對象展開操做(object spread operator)而不是Object.assign。使用對象剩餘操做符(object rest operator)獲取對象中剩餘的屬性。

    爲何? Object.assign使用不當會修改原對象
    // very bad
    const original = { a: 1, b: 2 };
    const copy = Object.assign(original, { c: 3 }); // this mutates `original` ಠ_ಠ
    delete copy.a; // so does this
    
    // bad
    const original = { a: 1, b: 2 };
    const copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, b: 2, c: 3 }
    
    // good
    const original = { a: 1, b: 2 };
    const copy = { ...original, c: 3 }; // copy => { a: 1, b: 2, c: 3 }
    
    const { a, ...noA } = copy; // noA => { b: 2, c: 3 }

數組

  1. 使用字面量聲明數組。eslint: no-array-constructor

    // bad
    const items = new Array();
    
    // good
    const items = [];
  2. 向數組添加元素時,使用Arrary#push替代直接賦值。

    const someStack = [];
    
    // bad
    someStack[someStack.length] = 'abracadabra';
    
    // good
    someStack.push('abracadabra');
  3. 使用數組展開操做符...拷貝數組

    // bad
    const len = items.length;
    const itemsCopy = [];
    let i;
    
    for (i = 0; i < len; i += 1) {
      itemsCopy[i] = items[i];
    }
    
    // good
    const itemsCopy = [...items];
  4. 將類數組對象(array-like)轉換成數組時,使用...而不是Array.from

    const foo = document.querySelectorAll('.foo');
    
    // good
    const nodes = Array.from(foo);
    
    // best
    const nodes = [...foo];
  5. 當須要對可遍歷對象進行map操做時,使用Array.from而不是展開操做符...,避免新建一個臨時數組。

    // bad
    const baz = [...foo].map(bar);
    
    // good
    const baz = Array.from(foo, bar);
  6. 數組方法回調須要有返回值。若是函數體比較簡單,能夠直接用表達式,省略return語句。 eslint: array-callback-return

    // good
    [1, 2, 3].map((x) => {
      const y = x + 1;
      return x * y;
    });
    
    // good
    [1, 2, 3].map(x => x + 1);
    
    // bad - no returned value means `memo` becomes undefined after the first iteration
    [[0, 1], [2, 3], [4, 5]].reduce((memo, item, index) => {
      const flatten = memo.concat(item);
      memo[index] = flatten;
    });
    
    // good
    [[0, 1], [2, 3], [4, 5]].reduce((memo, item, index) => {
      const flatten = memo.concat(item);
      memo[index] = flatten;
      return flatten;
    });
    
    // bad
    inbox.filter((msg) => {
      const { subject, author } = msg;
      if (subject === 'Mockingbird') {
        return author === 'Harper Lee';
      } else {
        return false;
      }
    });
    
    // good
    inbox.filter((msg) => {
      const { subject, author } = msg;
      if (subject === 'Mockingbird') {
        return author === 'Harper Lee';
      }
    
      return false;
    });
  7. 若是數組有多行,請在打開和關閉數組括號以前使用換行符

    爲何? 更具備可讀性
    // bad
    const arr = [
      [0, 1], [2, 3], [4, 5],
    ];
    
    const objectInArray = [{
      id: 1,
    }, {
      id: 2,
    }];
    
    const numberInArray = [
      1, 2,
    ];
    
    // good
    const arr = [[0, 1], [2, 3], [4, 5]];
    
    const objectInArray = [
      {
        id: 1,
      },
      {
        id: 2,
      },
    ];
    
    const numberInArray = [
      1,
      2,
    ];

解構

  1. 訪問和使用對象的多個屬性時用對象解構操做。eslint: prefer-destructuring jscs: requireObjectDestructuring

    爲何?解構能夠避免爲這些屬性建立臨時引用。
    // bad
    function getFullName(user) {
      const firstName = user.firstName;
      const lastName = user.lastName;
    
      return `${firstName} ${lastName}`;
    }
    
    // good
    function getFullName(user) {
      const { firstName, lastName } = user;
      return `${firstName} ${lastName}`;
    }
    
    // best
    function getFullName({ firstName, lastName }) {
      return `${firstName} ${lastName}`;
    }
  2. 使用數組解構。eslint: prefer-destructuring jscs: requireArrayDestructuring

    const arr = [1, 2, 3, 4];
    
    // bad
    const first = arr[0];
    const second = arr[1];
    
    // good
    const [first, second] = arr;
  3. 使用對象解構來實現多個返回值,而不是數組解構。jscs: disallowArrayDestructuringReturn

    爲何?你能夠隨時爲返回值新增屬性而不用關心屬性的順序。
    // bad
    function processInput(input) {
      // then a miracle occurs
      return [left, right, top, bottom];
    }
    
    // 調用者須要注意返回值中對象的順序
    const [left, __, top] = processInput(input);
    
    // good
    function processInput(input) {
      // then a miracle occurs
      return { left, right, top, bottom };
    }
    
    // 調用者只須要使用它須要的對象
    const { left, top } = processInput(input);

字符串

  1. 字符串使用單引號。eslint: quotes jscs: validateQuoteMarks

    // bad
    const name = "Capt. Janeway";
    
    // bad - 當須要插值或者換行時才使用模板文字
    const name = `Capt. Janeway`;
    
    // good
    const name = 'Capt. Janeway';
  2. 不超過100個字符的字符串不該該使用鏈接符或者換行書寫。

    爲何?換行的字符串很差閱讀,而且不方便搜索代碼。
    // bad
    const 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
    const 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
    const 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.';
  3. 以編程方式構建字符串時,使用模板字符串而不是鏈接符。eslint: prefer-template template-curly-spacing jscs: requireTemplateStrings

    爲何?模板字符串更爲簡潔,更具可讀性。
    // bad
    function sayHi(name) {
      return 'How are you, ' + name + '?';
    }
    
    // bad
    function sayHi(name) {
      return ['How are you, ', name, '?'].join();
    }
    
    // bad
    function sayHi(name) {
      return `How are you, ${ name }?`;
    }
    
    // good
    function sayHi(name) {
      return `How are you, ${name}?`;
    }
  4. 永遠不要在字符串上使用eval()方法,它有太多的問題。eslint: no-eval
  5. 不要過多的轉義字符串。eslint: no-useless-escape

    爲何?反斜槓影響代碼可讀性,只有在必要的時候才使用。
    // bad
    const foo = '\'this\' \i\s \"quoted\"';
    
    // good
    const foo = '\'this\' is "quoted"';
    const foo = `my name is '${name}'`;

函數

  1. 使用命名函數表達式而不是函數聲明。eslint: func-style jscs: disallowFunctionDeclarations

    爲何?函數聲明會被提早。這意味着極可能在函數定義前引用該函數,可是不會報錯。這不利於代碼的可讀性和可維護性。若是你發現一個函數定義的很大很複雜,以致於妨礙了了解文件中的其餘內容,那麼是時候把這個函數提取到本身的模塊中去了!不要忘記顯示指定表達式的名稱,儘管它能從變量名中被推斷出來(現代瀏覽器或者編譯器(如Babel)支持)。這能讓錯誤的調用棧更清晰。( 討論)
    // bad
    function foo() {
      // ...
    }
    
    // bad
    const foo = function () {
      // ...
    };
    
    // good
    // 函數名和變量引用名不一樣
    const short = function longUniqueMoreDescriptiveLexicalFoo() {
      // ...
    };
    // Is it worse
    const sum = function(a, b) {
      return a + b;
    };
    
    // than this?
    const my_sum = function sum(a, b) {
      return a + b;
    };
    第一個函數沒有 .name屬性,在debugging過程當中,它會是一個匿名函數。第二個函數有名字爲 sum,你能夠檢索到它,調試過程當中可以快速定位。

    使用banel 和babel-preset-env配置,const foo = () => {}會轉換成var foo = function foo () {},而且從Node v6開始,const foo = () => {}中的foo 也有.name。因此它再也不是匿名函數。(函數名字推斷)

  2. 用圓括號包裹當即執行函數表達式(IIFE)。eslint: wrap-iife jscs: requireParenthesesAroundIIFE

    爲何? 當即執行函數表達式是單一執行單元-使用圓括號包裹調用,簡潔明瞭的表示了這一點。請注意,在通用的模塊中,你幾乎用不到IIFE。
    // immediately-invoked function expression (IIFE)
    (function () {
      console.log('Welcome to the Internet. Please follow me.');
    }());
  3. 永遠不要在一個非函數代碼塊(if、while 等)中聲明一個函數,把那個函數賦給一個變量。瀏覽器容許你這麼作,但它們的解析表現不一致。eslint: no-loop-func
  4. 注意:ECMA-262把block定義爲一組語句。可是函數聲明不是語句。

    // bad
    if (currentUser) {
      function test() {
        console.log('Nope.');
      }
    }
    
    // good
    let test;
    if (currentUser) {
      test = () => {
        console.log('Yup.');
      };
    }
  5. 永遠不要把參數命名爲arguments。這將取代原來函數做用域內的 arguments對象。

    // bad
    function foo(name, options, arguments) {
      // ...
    }
    
    // good
    function foo(name, options, args) {
      // ...
    }
  6. 不要使用arguments。能夠選擇 rest 語法 ... 替代。

    爲何?使用 ... 能明確你要傳入的參數。另外 rest 參數是一個真正的數組,而 arguments 是一個類數組。
    // bad
    function concatenateAll() {
      const args = Array.prototype.slice.call(arguments);
      return args.join('');
    }
    
    // good
    function concatenateAll(...args) {
      return args.join('');
    }
  7. 使用函數默認參數指定默認值,而不是用一個可變的函數參數

    // really bad
    function handleThings(opts) {
      // 不!咱們不該該改變函數參數
      // 更糟糕的是: 若是 opts 是 falsy (爲''或者是false), 它仍然會被賦值爲對象,可是這可能會引起bug
      opts = opts || {};
      // ...
    }
    
    // still bad
    function handleThings(opts) {
      if (opts === void 0) {
        opts = {};
      }
      // ...
    }
    
    // good
    function handleThings(opts = {}) {
      // ...
    }

8.使用函數參數默認值的時避免反作用。

> 爲何?這樣的寫法會讓人困惑。

```javascript
var b = 1;
// bad
function count(a = b++) {
  console.log(a);
}
count();  // 1
count();  // 2
count(3); // 3
count();  // 3
```
  1. 參數默認值放在函數參數列表的最後。

    // bad
    function handleThings(opts = {}, name) {
      // ...
    }
    
    // good
    function handleThings(name, opts = {}) {
      // ...
    }
  2. 不要使用Function構造器建立函數。 eslint: no-new-func

    爲何?經過這種方式建立的函數和使用 eval()相似,會帶來不肯定的問題
    // bad
    var add = new Function('a', 'b', 'return a + b');
    
    // still bad
    var subtract = Function('a', 'b', 'return a - b');
  3. 函數名兩邊留白。eslint: space-before-function-paren [space-before-blocks]

    爲何?保持代碼一致性,當你添加或者刪除名字時不須要額外增減空格。
    // bad
    const f = function(){};
    const g = function (){};
    const h = function() {};
    
    // good
    const x = function () {};
    const y = function a() {};
  4. 不要修改參數。 eslint: no-param-reassign

    爲何?操做參數對象會在原始調用方中致使不可預知的變量反作用。
    // bad
    function f1(obj) {
      obj.key = 1;
    }
    
    // good
    function f2(obj) {
      const key = Object.prototype.hasOwnProperty.call(obj, 'key') ? obj.key : 1;
    }
  5. 不要給參數賦值。eslint: no-param-reassign

    爲何?從新分配參數可能會致使意外的行爲,特別是在訪問參數對象時。 它也可能致使優化問題,特別是在V8中。
    // bad
    function f1(a) {
      a = 1;
      // ...
    }
    
    function f2(a) {
      if (!a) { a = 1; }
      // ...
    }
    
    // good
    function f3(a) {
      const b = a || 1;
      // ...
    }
    
    function f4(a = 1) {
      // ...
    }
  6. 使用展開操做符...調用可變參數函數。eslint: prefer-spread

    爲何?它更簡潔,你不須要提供上下文,而且組合使用 newapply不容易。
    // bad
    const x = [1, 2, 3, 4, 5];
    console.log.apply(console, x);
    
    // good
    const x = [1, 2, 3, 4, 5];
    console.log(...x);
    
    // bad
    new (Function.prototype.bind.apply(Date, [null, 2016, 8, 5]));
    
    // good
    new Date(...[2016, 8, 5]);
  7. 帶有多行函數簽名或調用的函數應該像本指南中的其餘多行列表同樣縮進:每行中包含一項,最後一個項目帶有逗號。

    // bad
    function foo(bar,
                 baz,
                 quux) {
      // ...
    }
    
    // good
    function foo(
      bar,
      baz,
      quux,
    ) {
      // ...
    }
    
    // bad
    console.log(foo,
      bar,
      baz);
    
    // good
    console.log(
      foo,
      bar,
      baz,
    );

箭頭函數

  1. 當你必需要使用匿名函數(如在傳遞內聯回調時),請使用箭頭函數。eslint: prefer-arrow-callback, arrow-spacing jscs: requireArrowFunctions

    爲何?由於箭頭函數創造了新的一個 this 執行環境,一般狀況下都能知足你的需求,並且這樣的寫法更爲簡潔。(參考 Arrow functions - JavaScript | MDN

    爲何不?若是你有一個至關複雜的函數,你或許能夠把邏輯部分轉移到一個函數聲明上。

    // bad
    [1, 2, 3].map(function (x) {
      const y = x + 1;
      return x * y;
    });
    
    // good
    [1, 2, 3].map((x) => {
      const y = x + 1;
      return x * y;
    });
  2. 若是一個函數適合用一行寫出而且只有一個參數,那就把花括號、圓括號和 return 都省略掉。若是不是,那就不要省略。eslint: arrow-parens, arrow-body-style jscs: disallowParenthesesAroundArrowParam, requireShorthandArrowFunctions

    爲何?這是一個很好用的語法糖。在鏈式調用中可讀性很高。
    // bad
    [1, 2, 3].map(number => {
      const nextNumber = number + 1;
      `A string containing the ${nextNumber}.`;
    });
    
    // good
    [1, 2, 3].map(number => `A string containing the ${number}.`);
    
    // good
    [1, 2, 3].map((number) => {
      const nextNumber = number + 1;
      return `A string containing the ${nextNumber}.`;
    });
    
    // good
[index]: number,
}));

// No implicit return with side effects
function foo(callback) {
  const val = callback();
  if (val === true) {
    // Do something if callback returns true
  }
}

let bool = false;

// bad
foo(() => bool = true);

// good
foo(() => {
  bool = true;
});
```
  1. 若是表達式過長鬚要多行表示,請將其包含在括號中,增長可讀性。

    爲何?它能清除的標識函數的開始和結束位置。
    // bad
    ['get', 'post', 'put'].map(httpMethod => Object.prototype.hasOwnProperty.call(
        httpMagicObjectWithAVeryLongName,
        httpMethod,
      )
    );
    
    // good
    ['get', 'post', 'put'].map(httpMethod => (
      Object.prototype.hasOwnProperty.call(
        httpMagicObjectWithAVeryLongName,
        httpMethod,
      )
    ));
  2. 若是函數只有一個參數而且函數體沒有使用花括號,那就省略括號。不然,爲了保持清晰一致性,總在參數周圍加上括號。老是使用括號也是能夠接受的,在這種狀況下使用eslint的 「always」 option 或者不要在jscs中引入 disallowParenthesesAroundArrowParam。eslint: arrow-parens jscs: disallowParenthesesAroundArrowParam

    爲何? 不那麼混亂,可讀性強。
    // bad
    [1, 2, 3].map((x) => x * x);
    
    // good
    [1, 2, 3].map(x => x * x);
    
    // good
    [1, 2, 3].map(number => (
      `A long string with the ${number}. It’s so long that we don’t want it to take up space on the .map line!`
    ));
    
    // bad
    [1, 2, 3].map(x => {
      const y = x + 1;
      return x * y;
    });
    
    // good
    [1, 2, 3].map((x) => {
      const y = x + 1;
      return x * y;
    });
  3. 避免箭頭函數語法(=>)和比較運算符(<=,=>)一塊兒使用時帶來的困惑。

    // bad
    const itemHeight = item => item.height > 256 ? item.largeSize : item.smallSize;
    
    // bad
    const itemHeight = (item) => item.height > 256 ? item.largeSize : item.smallSize;
    
    // good
    const itemHeight = item => (item.height > 256 ? item.largeSize : item.smallSize);
    
    // good
    const itemHeight = (item) => {
      const { height, largeSize, smallSize } = item;
      return height > 256 ? largeSize : smallSize;
    };

類 & 構造函數

  1. 老是使用class。避免直接操做prototype

    爲何? class語法更簡潔更易於理解。
    // bad
    function Queue(contents = []) {
      this.queue = [...contents];
    }
    Queue.prototype.pop = function () {
      const value = this.queue[0];
      this.queue.splice(0, 1);
      return value;
    };
    
    // good
    class Queue {
      constructor(contents = []) {
        this.queue = [...contents];
      }
      pop() {
        const value = this.queue[0];
        this.queue.splice(0, 1);
        return value;
      }
    }
  2. 使用extends繼承。

    爲何? 由於 extends 是一個內建的原型繼承方法而且不會破壞 instanceof。
    // bad
    const inherits = require('inherits');
    function PeekableQueue(contents) {
      Queue.apply(this, contents);
    }
    inherits(PeekableQueue, Queue);
    PeekableQueue.prototype.peek = function () {
      return this.queue[0];
    };
    
    // good
    class PeekableQueue extends Queue {
      peek() {
        return this.queue[0];
      }
    }
  3. 方法能夠返回 this 來幫助鏈式調用。

    // bad
    Jedi.prototype.jump = function () {
      this.jumping = true;
      return true;
    };
    
    Jedi.prototype.setHeight = function (height) {
      this.height = height;
    };
    
    const luke = new Jedi();
    luke.jump(); // => true
    luke.setHeight(20); // => undefined
    
    // good
    class Jedi {
      jump() {
        this.jumping = true;
        return this;
      }
    
      setHeight(height) {
        this.height = height;
        return this;
      }
    }
    
    const luke = new Jedi();
    
    luke.jump()
      .setHeight(20);
  4. 能夠寫一個自定義的 toString() 方法,但要確保它能正常運行而且不會引發反作用。

    class Jedi {
      constructor(options = {}) {
        this.name = options.name || 'no name';
      }
    
      getName() {
        return this.name;
      }
    
      toString() {
        return `Jedi - ${this.getName()}`;
      }
    }
  5. 類有默認構造器。一個空的構造函數或者只是重載父類構造函數是沒必要要的。eslint: no-useless-constructor

    // bad
    class Jedi {
      constructor() {}
    
      getName() {
        return this.name;
      }
    }
    
    // bad
    class Rey extends Jedi {
      constructor(...args) {
        super(...args);
      }
    }
    
    // good
    class Rey extends Jedi {
      constructor(...args) {
        super(...args);
        this.name = 'Rey';
      }
    }
  6. 避免重複的類成員。eslint: no-dupe-class-members

    爲何?重複的類成員聲明中只有最後一個生效-重複的聲明確定是一個錯誤。
    // bad
    class Foo {
      bar() { return 1; }
      bar() { return 2; }
    }
    
    // good
    class Foo {
      bar() { return 1; }
    }
    
    // good
    class Foo {
      bar() { return 2; }
    }

模塊

  1. 老是使用模組 (import/export) 而不是其餘非標準模塊系統。你能夠編譯爲你喜歡的模塊系統。

    爲何?模塊是將來,讓咱們開始邁向將來吧。
    // bad
    const AirbnbStyleGuide = require('./AirbnbStyleGuide');
    module.exports = AirbnbStyleGuide.es6;
    
    // ok
    import AirbnbStyleGuide from './AirbnbStyleGuide';
    export default AirbnbStyleGuide.es6;
    
    // best
    import { es6 } from './AirbnbStyleGuide';
    export default es6;
  2. 不要使用通配符 import

    爲何?這樣確保只有一個默認的export
    // bad
    import * as AirbnbStyleGuide from './AirbnbStyleGuide';
    
    // good
    import AirbnbStyleGuide from './AirbnbStyleGuide';
  3. 不要直接從importexport

    爲何?雖然一行代碼簡潔明瞭,但讓 importexport 各司其職讓事情能保持一致。
    // bad
    // filename es6.js
    export { es6 as default } from './AirbnbStyleGuide';
    
    // good
    // filename es6.js
    import { es6 } from './AirbnbStyleGuide';
    export default es6;
  4. 同一個路徑只使用一次import。eslint: no-duplicate-imports

    爲何?相同路徑有多個 import會致使代碼難以維護。
    // bad
    import foo from 'foo';
    // … some other imports … //
    import { named1, named2 } from 'foo';
    
    // good
    import foo, { named1, named2 } from 'foo';
    
    // good
    import foo, {
      named1,
      named2,
    } from 'foo';
  5. 不要export可變的綁定。 eslint: import/no-mutable-exports

    爲何?避免不肯定的可變量,特別是 export可變的綁定。若是某些特殊狀況須要使用這種場景,一般應該 export常量引用。
    // bad
    let foo = 3;
    export { foo };
    
    // good
    const foo = 3;
    export { foo };
  6. 模塊中只有單個export,最好使用default export 。 eslint: import/prefer-default-export

    爲何?一個文件最好只作一件事,這樣更具有可讀性和可維護性。
    // bad
    export function foo() {}
    
    // good
    export default function foo() {}
  7. 將全部的import語句放在文件的頂部。eslint: import/first

    爲何?因爲 imports會被提高,最好保持它們在頂部以防出現不可預期的行爲。
    // bad
    import foo from 'foo';
    foo.init();
    
    import bar from 'bar';
    
    // good
    import foo from 'foo';
    import bar from 'bar';
    
    foo.init();
  8. 多行import應該和多行數組和對象同樣有縮進。

    爲何?花括號須要遵循與指南中的每一個其餘花括號相同的縮進規則,末尾的逗號也同樣。
    // bad
    import {longNameA, longNameB, longNameC, longNameD, longNameE} from 'path';
    
    // good
    import {
      longNameA,
      longNameB,
      longNameC,
      longNameD,
      longNameE,
    } from 'path';
  9. 禁止在模塊導入語句中使用Webpack加載器語法。eslint: import/no-webpack-loader-syntax

    爲何?在 import中使用webpack 語法會將代碼耦合進bundler中。推薦在 webpack.config.js中配置loader 規則。
    // bad
    import fooSass from 'css!sass!foo.scss';
    import barCss from 'style!css!bar.css';
    
    // good
    import fooSass from 'foo.scss';
    import barCss from 'bar.css';
相關文章
相關標籤/搜索