2022 年 6 月 26 日

编码风格

我们的代码必须尽可能的简洁易读。

这实际上是编程的艺术——以正确且人类可读的方式处理复杂的任务并对其进行编码。良好的代码风格在很大程度上对此有所帮助。

语法

这里有一个备忘单,其中包含一些建议的规则(更多详细信息,请参见下文)

现在让我们详细讨论规则及其原因。

没有“必须”的规则

这里没有一成不变的东西。这些是风格偏好,而不是宗教教条。

大括号

在大多数 JavaScript 项目中,大括号以“埃及”风格编写,其中左括号与对应的关键字在同一行上——而不是在新行上。左括号前也应该有一个空格,如下所示

if (condition) {
  // do this
  // ...and that
  // ...and that
}

单行结构,例如 if (condition) doSomething(),是一个重要的边缘情况。我们应该使用大括号吗?

以下是带注释的变体,以便您可以自己判断它们的可读性

  1. 😠 初学者有时会这样做。不好!不需要大括号
    if (n < 0) {alert(`Power ${n} is not supported`);}
  2. 😠 拆分为没有大括号的单独行。永远不要这样做,在添加新行时容易出错
    if (n < 0)
      alert(`Power ${n} is not supported`);
  3. 😏 一行没有大括号——可以接受,如果它很短
    if (n < 0) alert(`Power ${n} is not supported`);
  4. 😃 最佳变体
    if (n < 0) {
      alert(`Power ${n} is not supported`);
    }

对于非常简短的代码,允许一行,例如 if (cond) return null。但代码块(最后一个变体)通常更具可读性。

行长

没有人喜欢阅读一行很长的水平代码。最好将它们拆分。

例如

// backtick quotes ` allow to split the string into multiple lines
let str = `
  ECMA International's TC39 is a group of JavaScript developers,
  implementers, academics, and more, collaborating with the community
  to maintain and evolve the definition of JavaScript.
`;

以及对于 if 语句

if (
  id === 123 &&
  moonPhase === 'Waning Gibbous' &&
  zodiacSign === 'Libra'
) {
  letTheSorceryBegin();
}

最大行长应在团队级别达成一致。通常是 80 或 120 个字符。

缩进

缩进有两种类型

  • 水平缩进:2 或 4 个空格。

    水平缩进使用 2 或 4 个空格或水平制表符符号(键 Tab)进行。选择哪一个是一个古老的圣战。现在空格更常见。

    空格比制表符的一个优势是,空格允许比制表符符号更灵活地配置缩进。

    例如,我们可以将参数与左括号对齐,如下所示

    show(parameters,
         aligned, // 5 spaces padding at the left
         one,
         after,
         another
      ) {
      // ...
    }
  • 垂直缩进:用于将代码拆分为逻辑块的空行。

    即使是单个函数通常也可以分为逻辑块。在下面的示例中,变量的初始化、主循环和返回结果是垂直拆分的

    function pow(x, n) {
      let result = 1;
      //              <--
      for (let i = 0; i < n; i++) {
        result *= x;
      }
      //              <--
      return result;
    }

    在有助于提高代码可读性的位置插入额外的换行符。没有垂直缩进的代码行数不应超过九行。

分号

每个语句后面都应该有分号,即使可以跳过。

有些语言中分号确实是可选的,并且很少使用。然而,在 JavaScript 中,有时换行符不会被解释为分号,从而使代码容易出错。在 代码结构 一章中了解更多相关信息。

如果您是一位经验丰富的 JavaScript 程序员,您可以选择一种无分号的代码风格,例如 StandardJS。否则,最好使用分号来避免可能的陷阱。大多数开发人员都使用分号。

嵌套层级

尽量避免嵌套代码太多层级。

例如,在循环中,有时最好使用 continue 指令来避免额外的嵌套。

例如,不要添加嵌套的 if 条件,如下所示

for (let i = 0; i < 10; i++) {
  if (cond) {
    ... // <- one more nesting level
  }
}

我们可以编写

for (let i = 0; i < 10; i++) {
  if (!cond) continue;
  ...  // <- no extra nesting level
}

使用 if/elsereturn 可以执行类似的操作。

例如,以下两个结构是相同的。

选项 1

function pow(x, n) {
  if (n < 0) {
    alert("Negative 'n' not supported");
  } else {
    let result = 1;

    for (let i = 0; i < n; i++) {
      result *= x;
    }

    return result;
  }
}

选项 2

function pow(x, n) {
  if (n < 0) {
    alert("Negative 'n' not supported");
    return;
  }

  let result = 1;

  for (let i = 0; i < n; i++) {
    result *= x;
  }

  return result;
}

第二个选项更易于阅读,因为 n < 0 的“特殊情况”在早期就已处理。完成检查后,我们可以继续执行“主”代码流,而无需进行额外的嵌套。

函数放置

如果你正在编写多个“辅助”函数以及使用这些函数的代码,则有三种方法可以组织这些函数。

  1. 在使用它们的代码上方声明函数

    // function declarations
    function createElement() {
      ...
    }
    
    function setHandler(elem) {
      ...
    }
    
    function walkAround() {
      ...
    }
    
    // the code which uses them
    let elem = createElement();
    setHandler(elem);
    walkAround();
  2. 代码在前,函数在后

    // the code which uses the functions
    let elem = createElement();
    setHandler(elem);
    walkAround();
    
    // --- helper functions ---
    function createElement() {
      ...
    }
    
    function setHandler(elem) {
      ...
    }
    
    function walkAround() {
      ...
    }
  3. 混合:在首次使用函数的地方声明函数。

大多数情况下,首选第二个变体。

这是因为在阅读代码时,我们首先想知道它做了什么。如果代码在前,那么从一开始就变得清晰。然后,我们可能根本不需要阅读函数,特别是如果它们的名称描述了它们实际执行的操作。

风格指南

风格指南包含有关“如何编写”代码的一般规则,例如使用哪些引号、缩进多少个空格、最大行长等。很多小事。

当团队的所有成员都使用相同的风格指南时,代码看起来是统一的,无论由哪个团队成员编写。

当然,团队始终可以编写自己的风格指南,但通常没有必要。有很多现有的指南可供选择。

一些流行的选择

如果您是新手开发者,请从本章开头的备忘单开始。然后,您可以浏览其他风格指南以获取更多想法,并决定您最喜欢哪一个。

自动化 Linter

Linter 是可以自动检查您的代码风格并提出改进建议的工具。

它们的好处在于,风格检查还可以发现一些错误,例如变量或函数名称中的错别字。由于此功能,即使您不想坚持特定的“代码风格”,也建议使用 Linter。

以下是一些著名的 Linting 工具

  • JSLint – 最早的 Linter 之一。
  • JSHint – 比 JSLint 更多设置。
  • ESLint – 可能是最新的。

它们都可以完成这项工作。作者使用 ESLint

大多数 Linter 都与许多流行的编辑器集成:只需在编辑器中启用插件并配置样式即可。

例如,对于 ESLint,您应该执行以下操作

  1. 安装 Node.js
  2. 使用命令 npm install -g eslint 安装 ESLint(npm 是一个 JavaScript 包安装程序)。
  3. 在 JavaScript 项目的根目录(包含所有文件的文件夹)中创建一个名为 .eslintrc 的配置文件。
  4. 为您的编辑器安装/启用与 ESLint 集成的插件。大多数编辑器都有一个。

以下是一个 .eslintrc 文件示例

{
  "extends": "eslint:recommended",
  "env": {
    "browser": true,
    "node": true,
    "es6": true
  },
  "rules": {
    "no-console": 0,
    "indent": 2
  }
}

这里的指令 "extends" 表示配置基于“eslint:recommended”设置集。之后,我们指定我们自己的。

还可以从网络下载样式规则集并对其进行扩展。有关安装的更多详细信息,请参阅 https://eslint.org.cn/docs/user-guide/getting-started

此外,某些 IDE 具有内置 Linting,这很方便,但不如 ESLint 可定制。

总结

本章(以及所引用的风格指南)中描述的所有语法规则都旨在提高代码的可读性。所有这些都是有争议的。

当我们考虑编写“更好的”代码时,我们应该问自己的问题是:“什么让代码更具可读性和更易于理解?”以及“什么可以帮助我们避免错误?”在选择和讨论代码风格时,这些是需要牢记的主要事项。

阅读流行的风格指南将使您能够了解有关代码风格趋势和最佳实践的最新想法。

任务

重要性:4

以下代码风格有什么问题?

function pow(x,n)
{
  let result=1;
  for(let i=0;i<n;i++) {result*=x;}
  return result;
}

let x=prompt("x?",''), n=prompt("n?",'')
if (n<=0)
{
  alert(`Power ${n} is not supported, please enter an integer number greater than zero`);
}
else
{
  alert(pow(x,n))
}

修复它。

你可以注意以下内容

function pow(x,n)  // <- no space between arguments
{  // <- figure bracket on a separate line
  let result=1;   // <- no spaces before or after =
  for(let i=0;i<n;i++) {result*=x;}   // <- no spaces
  // the contents of { ... } should be on a new line
  return result;
}

let x=prompt("x?",''), n=prompt("n?",'') // <-- technically possible,
// but better make it 2 lines, also there's no spaces and missing ;
if (n<=0)  // <- no spaces inside (n <= 0), and should be extra line above it
{   // <- figure bracket on a separate line
  // below - long lines can be split into multiple lines for improved readability
  alert(`Power ${n} is not supported, please enter an integer number greater than zero`);
}
else // <- could write it on a single line like "} else {"
{
  alert(pow(x,n))  // no spaces and missing ;
}

已修复的变体

function pow(x, n) {
  let result = 1;

  for (let i = 0; i < n; i++) {
    result *= x;
  }

  return result;
}

let x = prompt("x?", "");
let n = prompt("n?", "");

if (n <= 0) {
  alert(`Power ${n} is not supported,
    please enter an integer number greater than zero`);
} else {
  alert( pow(x, n) );
}
教程地图

注释

在评论之前阅读此内容…
  • 如果您有改进建议 - 请提交 GitHub 问题或提交拉取请求,而不是发表评论。
  • 如果您无法理解文章中的内容,请详细说明。
  • 要插入一些代码,请使用 <code> 标签,对于多行,请将其包装在 <pre> 标签中,对于 10 行以上,请使用沙盒 (plnkrjsbincodepen…)