为什么你不再需要 JavaScript(和 TypeScript)中的分号了

15,534

随着近两年前端工具领域的一些重大变化,我不仅重新考虑了前端的构建方式,还重新考虑了代码的编写方式。

我已经从WebpackParcel换到了Vite,从 JavaScript 换到了 TypeScript,基于类/对象的组件换到了基于 Hook/Composition 的组件。现在随着边缘计算的到来,也许我会花更多的时间使用 Next、Remix 和 Nuxt 等元框架。

最近,我一直在思考的一个多年来没有想过的东西:分号

其实,您对 JavaScript 的任何看法,都可能是对的。此时,有一个问题又被提出:我们真的需要 JavaScript 中的分号吗?

从技术的角度来说

从技术的角度来说,在现代的前端领域,这个问题的答案是否定的。

现在,几乎所有新的前端项目都以由 CLI 或者 npm 初始化程序开始的,它们都可以选择(或者默认包含)linting、格式化、转译和编译的工具。

我们设置这些基础标准,为了让开发的体验更好,并在团队之间保持代码一致。有了这些工具的帮助,我认为可以不要 JavaScript 中的分号。当然,这个问题没有正确答案,完全是个人喜好问题。

为什么说 JavaScript 中的分号很尴尬

需要明确说明的是,分号本身并不尴尬,尴尬的插入分号这件事儿。在技术上,分号有无是“可选的”,但是它确实会导致一些异常情况。

关于分号,ESLint 文档解释得很好,说明如下:

JavaScript 不需要在每条语句的末尾使用分号。在许多情况下,JavaScript 引擎可以确定分号应该在某个位置并自动添加它。该功能称为 自动分号插入 (ASI)  ,这被认为是 JavaScript 中更具争议的功能之一。

例如,下面的代码是正确的:

var name = "ESLint"

var website = "eslint.org";

在第一行,JavaScript 引擎会自动插入一个分号,所以这不被认为是语法错误。JavaScript 的引擎知道如何解释该行代码,并且知道行尾表示语句结束了。

分号可能会导致两种异常问题的发生:

  1. 无法访问的代码
  2. 意外的多行代码

首先,看第一点

示例代码如下:

return
{
    name: "ESLint"
};

JavaScript 引擎会将这段代码解释为:

return;
{
    name: "ESLint";
}

这样就会造成 return 后直接返回,导致它下面的代码无法访问。

然后,看第二点

示例代码如下:

var globalCounter = { }
 
(function () {
    var n = 0
    globalCounter.increment = function () {
        return ++n
    }
})()

JavaScript 引擎会将这段代码解释为:

var globalCounter = { }
 
(function () {
    var n = 0
    globalCounter.increment = function () {
        return ++n
    }
})();

JavaScript 引擎不会在第一行之后插入分号,从而导致运行时错误(误将空对象作为函数调用)。

使用工具

现在,我们已经了解了分号在 JavaScript 中是如何工作的。接下来介绍一下使用哪些工具可以避免上面遇到的异常情况。

常见的有三个工具:

  1. ESLint
  2. Prettier
  3. TypeScript Compiler (TSC) 这三个工具可以很好地协同工作,每个都可以针对前面描述的异常情况提供对应的保护机制。

ESLint

ESLint是最流行的 JavaScript linter。它的配置非常灵活,并带有开箱即用的推荐规则。

要配置 ESLint 在不使用分号的情况下也可以正常工作,只需要指定三个规则:semino-unreachableno-unexpected-multiline

可以将下面的代码片段添加到块.eslintrc.{js,yml,json}下的配置文件rule中:

rules: {
  semi: ['error', 'never'],
  'no-unreachable': ['error'],
  'no-unexpected-multiline': ['error']
}

Prettier

Prettier是一个专一的代码格式化工具,唯一的目的就是格式化你的代码。

一般情况下,Prettier 会与 ESLint 一起配合使用,效果更佳。

我们可以将 Prettier 配置为自动从代码中删除分号,需要在.prettierrc.json配置文件中增加如下设置:

{
  "semi": false
}

TSC

TypeScript 编译器是这三个工具中最简单的,因为它不需要配置就可以使用没有分号的语言。只要您使用 TypeScript 语言开发。

虽然它没有涵盖所有边缘情况,但当其中一些 ASI 故障导致对 TypeScript 类型系统的无效使用时,编译器会发出错误。

何时使用分号

尽管,上述工具可以帮助我们处理没有分号的异常情况,但是仍然有一些情况可以使用分号:

  • 直接在浏览器/网页中编写代码
  • 在没有良好工具支持的项目或环境中编写代码
  • 你是 JavaScript 新手
  • 只是因为你