JavaScript 的代码风格是该遵照 Google Style Guide 的指引, 还是信 StandardJS 的鬼话呢。。

这真是个令人纠结的问题。。呐, 曾经我是一个坚定的 Standard 党,明明 JavaScript 不需要分号嘛,加上分号真是画蛇添足。 直到有一天我写出了这样的代码:

(async function its () {
  console.log(`it's`)
})()

(async function wrong () {
  console.log('wrong')
})()
(async function wrong () {
^
TypeError: (intermediate value)(...) is not a function

我终于知道,哪怕中间空两行,怎么想都看不出两者的关系,也会被 JavaScript 解释器当成连续的函数调用。自此以后,我就改用 Google 的 Style 了。然而好景不长, 不久以后我又写出了这样的代码:

const goodOneShouldHaveFriends = true;
const sunriseFoxIsGoodEnough = true;
const check = function ifSunriseFoxShouldHaveAFriend() {
  return
    goodOneShouldHaveFriends && sunriseFoxIsGoodEnough;
}
const result = check();
if(result) console.log('sunrisefox will have a friend soon');
else console.log('sunrisefox will be alone forever');

好吧,结果显然是 sunrisefox will be alone forever 。 加分号真的是害死人啊啊啊啊啊啊(┬_┬) 于是我也讨厌它了(其实还是自己对 JavaScript 不熟悉啦)

于是以后决定开始尝试自己最开始接触 JavaScript 时遵照的 Airbnb Style 了,如果不行的话, 继续回到 Standard。

简介

Standard

顾名思义,Standard Style,就是官方不承认的、非标准的 JavaScript 代码风格(笑。 不管怎么说,总归没有一种代码风格适合所有项目。最好的话,还是自己写 eslint 规则才是。 或者,干脆自己写得爽就好了,要什么规则(然而在团队合作的时候可能会被打死)。

vampire 用的是 standard style 喵(>^ω^<)

// StandardJS
Promise.resolve().then(() =>
  42
).then(number => {
  conlose.log(number)
  return number
}).catch(error => {
  console.error(error.stack)
  return ~~(Math.random() * 100)
}).then(number =>
  console.log('got number: ', number)
)

Google

谷歌的 Style 相比 Standard 详细很多,而且,不光包含一些代码风格上的内容, 同时还有函数调用惯例、设计方式,等等。讨厌他的原因一方面也是因为他确实管得太宽泛啦,

// Google
Promise.resolve().then(() =>
  42
).then((number) => {
  conlose.log(number);
  return number;
}).catch((error) => {
  console.error(error.stack);
  return Math.random() * 100;
}).then((number) =>
  console.log('got number: ', number)
);

Airbnb

写的时候还没开始用,不过看上去有点...魔法?还要使用过才能评价

// Airbnb
Promise.resolve().then(() => 42).then((number) => {
  conlose.log(number);
  return number;
}).catch((error) => {
  console.error(error.stack);
  return ~~(Math.random() * 100);
})
  .then(number => console.log('got number: ', number));

配置

基本配置

在 eslint 的帮助下,配置它们还是非常非常简单的,只需要

npx eslint --init

然后就会自动地交互式地安装所希望的代码样式和配置文件啦。

对于 babel 项目来说,为了避免被奇怪的警告(比如类似 import() 未定义), 还要装一个 babel-eslint 并且放在配置文件的 parser 里面。

对于 vue 项目来说,为了能够正确处理 .vue 文件,还要来一个 eslint-plugin-vue。 最终,配置文件大概就会变成这个样子(我选择了 JavaScript 格式):

module.exports = {
  "extends": [
    "airbnb-base",
    "plugin:vue/essential"
  ],
  "parserOptions": {
    "parser": "babel-eslint",
    "ecmaVersion": 2018,
    "sourceType": "module"
  },
  "rules": {
    "no-unused-vars": ["error", { "vars": "all", "args": "after-used", "varsIgnorePattern": "^[A-Z]" }]
  }
};

自动化配置

为了每次可以愉快地格式化代码,我们可以添加一个 git pre commit hook 来自动地执行一些格式化操作,比如,用 husky 处理 Git Hooks,很方便,不需要写 bash 代码啦。

package.json:

"husky": {
  "hooks": {
    "pre-commit": "npx eslint --ext .js,.vue src --fix"
  }
}

当然,有时候可能并不想格式化全部文件。如果也不愿意处理格式化哪些文件,那么可以用 lint-staged 来自动地格式化 staged 文件

package.json:

"husky": {
  "hooks": {
    "pre-commit": "lint-staged"
  }
},
"lint-staged": {
  "*.{js,vue}": [
    "eslint --fix"
  ]
}

完整流程总结

对于已有 npm 项目:

npm i eslint -D
npx eslint --init

我的选择:

? How would you like to configure ESLint? Use a popular style guide
? Which style guide do you want to follow? Standard (https://github.com/standard/standard)
? What format do you want your config file to be in? JavaScript

需要安装(帮我们安装的)

npm i eslint-config-standard@latest eslint@>=5.0.0\
 eslint-plugin-import@>=2.13.0 eslint-plugin-node@>=7.0.0\
 eslint-plugin-promise@>=4.0.0 eslint-plugin-standard@>=4.0.0 -D

继续安装:

npm i babel-eslint eslint-plugin-vue -D

修改配置文件:

module.exports = {
  "extends": [
    "standard",
    "plugin:vue/essential"
  ],
  "parserOptions": {
    "parser": "babel-eslint",
    "ecmaVersion": 2018,
    "sourceType": "module"
  },
  "rules": {
    "no-unused-vars": ["error", { "vars": "all", "args": "after-used", "varsIgnorePattern": "^[A-Z]" }]
  }
}

测试一下

npx eslint --ext .js,.vue src

正常工作,不错哦!

安装 husky,添加 pre-commit hook:

npm i husky lint-staged -D

修改 package.json

"husky": {
  "hooks": {
    "pre-commit": "lint-staged"
  }
},
"lint-staged": {
  "*.{js,vue}": [
    "eslint --fix",
    "git add"
  ]
}

commit 一些文件试试看~ 如果出现了 husky 的提示,恭喜,成功啦!