Airbnb JavaScript 编码作风指南(2018年最新版)

Airbnb JavaScript 编码作风指南(2018年最新版)

接见此原文地点:
http://galaxyteam.pub/didi-fe…

别的迎接接见我们保护的
https://www.threejs.online 中文站
(迎接Star!)

本文译者:滴滴出行上海前端(FE)团队杨永乐同砚

范例

  1. 基础范例:直接存取

    • string
    • number
    • boolean
    • null
    • undefined
    • symbol
    const foo = 1;
    let bar = foo;
    
    bar = 9;
    
    console.log(foo, bar); // => 1, 9
    • symbol 范例不能完整polyfilled,所以请郑重运用
  2. 庞杂范例: 经由过程援用的体式格局存取

    • 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: disallowVar

    为何?比拟于
    var函数作用域,
    let块级作用域更轻易明白

    // bad
    var count = 1;
    if (true) {
      count += 1;
    }
    
    // good, use the let.
    let count = 1;
    if (true) {
      count += 1;
    }
  3. 注重letconst都是块级作用域

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

    // bad
    const item = new Object();
    
    // good
    const item = {};
  2. 建立对象的动态属性时,运用盘算属性

    为何?如许可以在一个处所定义对象一切的属性

    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: requireEnhancedObjectLiterals

    为何?要领定义简约清楚

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

    为何?誊写越发简约,更有描述性。

    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

    为何?它更简约,你不须要供应上下文,而且组合运用
    new
    apply不轻易。

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

    为何?虽然一行代码简约明了,但让
    import
    export 各司其职让事变能坚持一致。

    // 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';
    原文作者:谯洪敏
    原文地址: https://segmentfault.com/a/1190000013040555
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞