# JavaScript style guide

> 原文：[https://docs.gitlab.com/ee/development/fe_guide/style/javascript.html](https://docs.gitlab.com/ee/development/fe_guide/style/javascript.html)

*   [Avoid forEach](#avoid-foreach)
*   [Limit number of parameters](#limit-number-of-parameters)
*   [Avoid classes to handle DOM events](#avoid-classes-to-handle-dom-events)
*   [Pass element container to constructor](#pass-element-container-to-constructor)
*   [Use ParseInt](#use-parseint)
*   [CSS Selectors - Use `js-` prefix](#css-selectors---use-js--prefix)
*   [ES Module Syntax](#es-module-syntax)
*   [Absolute vs relative paths for modules](#absolute-vs-relative-paths-for-modules)
*   [Do not use `DOMContentLoaded` in non-page modules](#do-not-use-domcontentloaded-in-non-page-modules)
*   [Avoid XSS](#avoid-xss)
*   [Avoid single-line conditional statements](#avoid-single-line-conditional-statements)
*   [ESLint](#eslint)
*   [IIFEs](#iifes)
*   [Global namespace](#global-namespace)
*   [Side effects](#side-effects)
    *   [Top-level side effects](#top-level-side-effects)
    *   [Avoid side effects in constructors](#avoid-side-effects-in-constructors)
*   [Pure Functions and Data Mutation](#pure-functions-and-data-mutation)

# JavaScript style guide[](#javascript-style-guide "Permalink")

我们使用[Airbnb 的 JavaScript 样式指南](https://github.com/airbnb/javascript)及其附带的 linter 来管理我们的大多数 JavaScript 样式指南.

除了由 Airbnb 设置的样式准则之外，我们还列出了以下一些特定规则.

> **提示：**您可以通过运行`yarn eslint`在本地运行`yarn eslint`

## Avoid forEach[](#avoid-foreach "Permalink")

变异数据时避免 forEach. 更改数据时，请使用`map` ， `reduce`或`filter`而不是`forEach` . 这样可以最大程度地减少功能上的变化，从而与[Airbnb 的风格指南](https://github.com/airbnb/javascript#testing--for-real)保持一致.

```
// bad
users.forEach((user, index) => {
  user.id = index;
});

// good
const usersWithId = users.map((user, index) => {
  return Object.assign({}, user, { id: index });
}); 
```

## Limit number of parameters[](#limit-number-of-parameters "Permalink")

如果您的函数或方法具有三个以上的参数，请改为使用对象作为参数.

```
// bad
function a(p1, p2, p3) {
  // ...
};

// good
function a(p) {
  // ...
}; 
```

## Avoid classes to handle DOM events[](#avoid-classes-to-handle-dom-events "Permalink")

如果该类的唯一目的是绑定 DOM 事件并处理回调，则最好使用函数.

```
// bad
class myClass {
  constructor(config) {
    this.config = config;
  }

  init() {
    document.addEventListener('click', () => {});
  }
}

// good

const myFunction = () => {
  document.addEventListener('click', () => {
    // handle callback here
  });
} 
```

## Pass element container to constructor[](#pass-element-container-to-constructor "Permalink")

当您的类操作 DOM 时，将元素容器作为参数接收. 这样更易于维护和执行.

```
// bad
class a {
  constructor() {
    document.querySelector('.b');
  }
}

// good
class a {
  constructor(options) {
    options.container.querySelector('.b');
  }
} 
```

## Use ParseInt[](#use-parseint "Permalink")

将数字字符串转换为数字时，请使用`ParseInt` .

```
// bad
Number('10')

// good
parseInt('10', 10); 
```

## CSS Selectors - Use `js-` prefix[](#css-selectors---use-js--prefix "Permalink")

如果仅在 JavaScript 中使用 CSS 类作为对元素的引用，则使用`js-`作为类名的前缀.

```
// bad
<button class="add-user"></button>

// good
<button class="js-add-user"></button> 
```

## ES Module Syntax[](#es-module-syntax "Permalink")

使用 ES 模块语法导入模块：

```
// bad
const SomeClass = require('some_class');

// good
import SomeClass from 'some_class';

// bad
module.exports = SomeClass;

// good
export default SomeClass; 
```

*注意：*我们仍然在`scripts/`和`config/`文件中使用`require` .

## Absolute vs relative paths for modules[](#absolute-vs-relative-paths-for-modules "Permalink")

如果要导入的模块少于两个级别，请使用相对路径.

```
// bad
import GitLabStyleGuide from '~/guides/GitLabStyleGuide';

// good
import GitLabStyleGuide from '../GitLabStyleGuide'; 
```

如果要导入的模块为两个或两个以上级别，请改用绝对路径：

```
// bad
import GitLabStyleGuide from '../../../guides/GitLabStyleGuide';

// good
import GitLabStyleGuide from '~/GitLabStyleGuide'; 
```

Additionally, **不添加到全局名称空间**.

## Do not use `DOMContentLoaded` in non-page modules[](#do-not-use-domcontentloaded-in-non-page-modules "Permalink")

导入的模块每次加载时都应发挥相同的作用. `DOMContentLoaded`事件仅允许在`/pages/*`目录中加载的模块上使用，因为这些事件是通过 webpack 动态加载的.

## Avoid XSS[](#avoid-xss "Permalink")

不要使用`innerHTML` ， `append()`或`html()`设置内容. 它打开了太多的漏洞.

## Avoid single-line conditional statements[](#avoid-single-line-conditional-statements "Permalink")

缩进在扫描代码时很重要，因为它可以快速指示分支，循环和返回点的存在. 这可以帮助快速了解控制流程.

```
// bad
if (isThingNull) return '';

if (isThingNull)
  return '';

// good
if (isThingNull) {
  return '';
} 
```

## ESLint[](#eslint "Permalink")

ESLint 行为可以在我们的[工具指南中](../tooling.html)找到.

## IIFEs[](#iifes "Permalink")

避免使用 IIFE（立即调用函数表达式）. 尽管我们有很多将其内容包装在 IIFE 中的文件示例，但是从 Sprockets 过渡到 Webpack 之后，这不再是必需的. 重构遗留代码时，请不要再使用它们，并随时将其删除.

## Global namespace[](#global-namespace "Permalink")

避免添加到全局名称空间.

```
// bad
window.MyClass = class { /* ... */ };

// good
export default class MyClass { /* ... */ } 
```

## Side effects[](#side-effects "Permalink")

### Top-level side effects[](#top-level-side-effects "Permalink")

在任何包含`export`脚本中都禁止顶级副作用：

```
// bad
export default class MyClass { /* ... */ }

document.addEventListener("DOMContentLoaded", function(event) {
  new MyClass();
} 
```

### Avoid side effects in constructors[](#avoid-side-effects-in-constructors "Permalink")

避免在`constructor`进行异步调用，API 请求或 DOM 操作. 而是将它们移动到单独的函数中. 这将使测试更易于编写，并且避免违反[单一职责原则](https://en.wikipedia.org/wiki/Single_responsibility_principle) .

```
// bad
class myClass {
  constructor(config) {
    this.config = config;
    axios.get(this.config.endpoint)
  }
}

// good
class myClass {
  constructor(config) {
    this.config = config;
  }

  makeRequest() {
    axios.get(this.config.endpoint)
  }
}
const instance = new myClass();
instance.makeRequest(); 
```

## Pure Functions and Data Mutation[](#pure-functions-and-data-mutation "Permalink")

努力编写许多小的纯函数，并尽量减少发生突变的地方

```
 // bad
  const values = {foo: 1};

  function impureFunction(items) {
    const bar = 1;

    items.foo = items.a * bar + 2;

    return items.a;
  }

  const c = impureFunction(values);

  // good
  var values = {foo: 1};

  function pureFunction (foo) {
    var bar = 1;

    foo = foo * bar + 2;

    return foo;
  }

  var c = pureFunction(values.foo); 
```