JavaScript style guide

原文:https://docs.gitlab.com/ee/development/fe_guide/style/javascript.html

JavaScript style guide

我们使用Airbnb 的 JavaScript 样式指南及其附带的 linter 来管理我们的大多数 JavaScript 样式指南.

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

提示:您可以通过运行yarn eslint在本地运行yarn eslint

Avoid forEach

变异数据时避免 forEach. 更改数据时,请使用mapreducefilter而不是forEach . 这样可以最大程度地减少功能上的变化,从而与Airbnb 的风格指南保持一致.

  1. // bad
  2. users.forEach((user, index) => {
  3. user.id = index;
  4. });
  5. // good
  6. const usersWithId = users.map((user, index) => {
  7. return Object.assign({}, user, { id: index });
  8. });

Limit number of parameters

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

  1. // bad
  2. function a(p1, p2, p3) {
  3. // ...
  4. };
  5. // good
  6. function a(p) {
  7. // ...
  8. };

Avoid classes to handle DOM events

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

  1. // bad
  2. class myClass {
  3. constructor(config) {
  4. this.config = config;
  5. }
  6. init() {
  7. document.addEventListener('click', () => {});
  8. }
  9. }
  10. // good
  11. const myFunction = () => {
  12. document.addEventListener('click', () => {
  13. // handle callback here
  14. });
  15. }

Pass element container to constructor

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

  1. // bad
  2. class a {
  3. constructor() {
  4. document.querySelector('.b');
  5. }
  6. }
  7. // good
  8. class a {
  9. constructor(options) {
  10. options.container.querySelector('.b');
  11. }
  12. }

Use ParseInt

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

  1. // bad
  2. Number('10')
  3. // good
  4. parseInt('10', 10);

CSS Selectors - Use js- prefix

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

  1. // bad
  2. <button class="add-user"></button>
  3. // good
  4. <button class="js-add-user"></button>

ES Module Syntax

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

  1. // bad
  2. const SomeClass = require('some_class');
  3. // good
  4. import SomeClass from 'some_class';
  5. // bad
  6. module.exports = SomeClass;
  7. // good
  8. export default SomeClass;

注意:我们仍然在scripts/config/文件中使用require .

Absolute vs relative paths for modules

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

  1. // bad
  2. import GitLabStyleGuide from '~/guides/GitLabStyleGuide';
  3. // good
  4. import GitLabStyleGuide from '../GitLabStyleGuide';

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

  1. // bad
  2. import GitLabStyleGuide from '../../../guides/GitLabStyleGuide';
  3. // good
  4. import GitLabStyleGuide from '~/GitLabStyleGuide';

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

Do not use DOMContentLoaded in non-page modules

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

Avoid XSS

不要使用innerHTMLappend()html()设置内容. 它打开了太多的漏洞.

Avoid single-line conditional statements

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

  1. // bad
  2. if (isThingNull) return '';
  3. if (isThingNull)
  4. return '';
  5. // good
  6. if (isThingNull) {
  7. return '';
  8. }

ESLint

ESLint 行为可以在我们的工具指南中找到.

IIFEs

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

Global namespace

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

  1. // bad
  2. window.MyClass = class { /* ... */ };
  3. // good
  4. export default class MyClass { /* ... */ }

Side effects

Top-level side effects

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

  1. // bad
  2. export default class MyClass { /* ... */ }
  3. document.addEventListener("DOMContentLoaded", function(event) {
  4. new MyClass();
  5. }

Avoid side effects in constructors

避免在constructor进行异步调用,API 请求或 DOM 操作. 而是将它们移动到单独的函数中. 这将使测试更易于编写,并且避免违反单一职责原则 .

  1. // bad
  2. class myClass {
  3. constructor(config) {
  4. this.config = config;
  5. axios.get(this.config.endpoint)
  6. }
  7. }
  8. // good
  9. class myClass {
  10. constructor(config) {
  11. this.config = config;
  12. }
  13. makeRequest() {
  14. axios.get(this.config.endpoint)
  15. }
  16. }
  17. const instance = new myClass();
  18. instance.makeRequest();

Pure Functions and Data Mutation

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

  1. // bad
  2. const values = {foo: 1};
  3. function impureFunction(items) {
  4. const bar = 1;
  5. items.foo = items.a * bar + 2;
  6. return items.a;
  7. }
  8. const c = impureFunction(values);
  9. // good
  10. var values = {foo: 1};
  11. function pureFunction (foo) {
  12. var bar = 1;
  13. foo = foo * bar + 2;
  14. return foo;
  15. }
  16. var c = pureFunction(values.foo);