ESLint 是什么?为什么你的项目需要它?

从"代码能跑就行"到"代码能跑且优雅",中间隔着一个 ESLint。

一句话回答

ESLint 是一个 JavaScript/TypeScript 代码静态分析工具------它不运行你的代码,而是读你的代码,找出里面的语法错误、坏味道和不一致的风格,然后告诉你哪里该改、怎么改。


为什么需要 ESLint?

1. 拦截低级错误,趁早不赶晚

js 复制代码
// 你觉得这段代码有什么问题?
if (isAdmin = true) {
  deleteUserAccount();
}

= 写成了 ==?不,是赋值写进了 if 条件里。这段代码能跑,不会报语法错误,但它会在你不注意的时候把用户账号删了。ESLint 的 no-cond-assign 规则会在你写下的那一刻就标红警告。

类似的还有:

  • 变量声明了但没使用(no-unused-vars
  • console.log 忘了删(no-console
  • return 后面写了不可达代码(no-unreachable
  • ===== 混用(eqeqeq

这些 bug 在运行时往往很难排查,但在静态分析阶段花 0.1 秒就能发现。

2. 统一团队风格,消灭无意义的 Code Review 争论

"花括号应该写同一行还是换行?" "缩进用 tab 还是空格?" "分号加不加?"

这些问题不该出现在 Code Review 里。它们没有对错,但一旦团队不统一,阅读代码时就会产生认知负担。ESLint 把这些风格决策固化成规则,代码提交前自动检查,不符合就报错。

js 复制代码
// ESLint 让团队的代码长成同一个样子
const foo = () => {
  if (condition) {
    doSomething();
  }
};

3. 强制执行最佳实践

JavaScript 有很多"能跑但不好"的写法。ESLint 内置了大量最佳实践规则:

规则 防止什么
no-var 鼓励用 let/const 替代 var,避免变量提升陷阱
prefer-const 声明后不修改的变量必须用 const
no-eval 禁止 eval(),防止注入攻击
no-implicit-globals 禁止意外创建全局变量
prefer-arrow-callback 鼓励箭头函数,减少 this 绑定问题
no-duplicate-case 防止 switch 里写重复的 case

4. 与编辑器深度集成,实时反馈

VS Code、WebStorm 等编辑器都支持 ESLint 插件。你写代码的同时,编辑器就能:

  • 在有问题的代码下画红色波浪线
  • 显示具体问题和修复建议
  • 一键自动修复--fix

这种"写错即纠"的体验,比等 CI 跑完才发现问题高效得多。


ESLint 的工作原理

ESLint 的核心流程可以概括为三步:

解析 → 遍历 → 报告

  1. 解析 :ESLint 把你的源代码解析成 AST(抽象语法树)。JavaScript 用 Espree 解析器,TypeScript 需要配合 @typescript-eslint/parser
  2. 遍历:ESLint 遍历 AST 的每个节点,每碰到一个节点就检查有没有匹配的规则。
  3. 报告 :匹配到规则后,根据规则配置(off / warn / error)输出对应级别的诊断信息。

插件 提供规则,配置 决定哪些规则开启、开到什么级别。这就是 ESLint "插件 + 配置" 的设计哲学。


快速上手

安装

bash 复制代码
npm install -D eslint

初始化配置

bash 复制代码
npx eslint --init

ESLint 会问你几个问题(项目类型、框架、是否用 TypeScript 等),然后生成 .eslintrc.js

js 复制代码
// .eslintrc.js --- 旧版配置格式(eslintrc)
module.exports = {
  env: {
    browser: true,
    es2021: true,
    node: true,
  },
  extends: 'eslint:recommended',
  parserOptions: {
    ecmaVersion: 2021,
    sourceType: 'module',
  },
  rules: {
    'no-unused-vars': 'warn',
    'no-console': 'warn',
    'eqeqeq': 'error',
    'prefer-const': 'error',
  },
};

新版配置格式(Flat Config)

ESLint 9+ 默认使用扁平化配置 eslint.config.js

js 复制代码
// eslint.config.js
import js from '@eslint/js';

export default [
  js.configs.recommended,
  {
    rules: {
      'no-unused-vars': 'warn',
      'no-console': 'warn',
      'eqeqeq': 'error',
    },
  },
];

扁平配置用数组代替继承链,更直观、更容易理解每条规则从哪来。

运行

bash 复制代码
# 检查所有文件
npx eslint .

# 检查并自动修复
npx eslint . --fix

# 只检查特定文件
npx eslint src/**/*.js

配合 npm scripts

json 复制代码
{
  "scripts": {
    "lint": "eslint .",
    "lint:fix": "eslint . --fix"
  }
}

常用规则速查

错误检测类

js 复制代码
rules: {
  'no-unused-vars': 'error',      // 声明但未使用的变量
  'no-undef': 'error',            // 使用未定义的变量
  'no-unreachable': 'error',      // return 后的不可达代码
  'no-cond-assign': 'error',      // 条件语句中出现赋值
  'no-debugger': 'error',         // debugger 语句
}

风格规范类

js 复制代码
rules: {
  'indent': ['error', 2],              // 统一缩进 2 空格
  'quotes': ['error', 'single'],       // 统一单引号
  'semi': ['error', 'always'],         // 强制分号
  'no-trailing-spaces': 'error',       // 禁止行尾空格
  'eol-last': 'error',                 // 文件末尾空行
}

最佳实践类

js 复制代码
rules: {
  'eqeqeq': 'error',              // 必须用 === 而非 ==
  'no-eval': 'error',             // 禁止 eval
  'no-var': 'error',              // 禁止 var
  'prefer-const': 'error',        // 优先用 const
  'no-multiple-empty-lines': ['error', { max: 2 }],
}

建议:风格类规则交给 Prettier 处理,ESLint 专注代码质量和最佳实践,两者各司其职。后面会展开说。


与 Prettier 的关系

很多人搞不清 ESLint 和 Prettier 的区别,简单说:

ESLint Prettier
关注什么 代码质量 + 代码风格 纯代码格式化
典型问题 未使用的变量、== vs ===、不可达代码 缩进、引号、换行、行宽
能修复逻辑吗 能发现问题,部分能自动修复 不能,只改格式不改逻辑
能配规则吗 能,几百条 几乎不能,只有几个选项

最佳实践:两者一起用。

  • ESLint 负责"代码对不对"
  • Prettier 负责"代码好不好看"
  • eslint-config-prettier 关闭 ESLint 中与 Prettier 冲突的格式化规则
bash 复制代码
npm install -D prettier eslint-config-prettier
js 复制代码
// .eslintrc.js
module.exports = {
  extends: [
    'eslint:recommended',
    'prettier',  // 放最后,关闭冲突的格式规则
  ],
};

TypeScript 项目怎么配?

TypeScript 项目需要额外的解析器和插件:

bash 复制代码
npm install -D @typescript-eslint/parser @typescript-eslint/eslint-plugin
js 复制代码
// eslint.config.js
import js from '@eslint/js';
import tseslint from 'typescript-eslint';

export default tseslint.config(
  js.configs.recommended,
  ...tseslint.configs.recommended,
  {
    rules: {
      '@typescript-eslint/no-unused-vars': 'warn',
      '@typescript-eslint/no-explicit-any': 'warn',
    },
  },
);

@typescript-eslint 能检查类型层面的错误,比如:

  • 显式使用 any 类型(no-explicit-any
  • 非空断言 ! 滥用(no-non-null-assertion
  • 不安全的类型断言(no-unsafe-assertion

配合 Git Hook 自动化

最理想的状态是:代码提交前自动检查,不合格的代码根本进不了仓库。

用 lint-staged + husky

bash 复制代码
npm install -D husky lint-staged
npx husky init
json 复制代码
// package.json
{
  "scripts": {
    "prepare": "husky"
  },
  "lint-staged": {
    "*.{js,ts,jsx,tsx}": "eslint --fix"
  }
}
bash 复制代码
echo "npx lint-staged" > .husky/pre-commit

这样每次 git commit 时,ESLint 会自动检查暂存区的文件,有问题就阻止提交。只有新增/修改的文件会被检查,不会全量扫描,速度很快。


常见配置预设

与其从零配置,不如站在巨人肩膀上。社区提供了很多成熟的配置预设:

预设 特点
eslint:recommended ESLint 官方推荐,覆盖最常见的错误检测
eslint-config-airbnb Airbnb 的严格风格规范,曾经是社区标准
eslint-config-standard 标准风格,无分号、无冗余配置
eslint-config-next Next.js 官方配置,包含 React + a11y 规则
eslint-config-react-app CRA 内置配置
eslint-config-prettier 关闭与 Prettier 冲突的规则
js 复制代码
// 组合使用
export default [
  js.configs.recommended,
  ...reactHooks.configs.recommended,
  ...reactRefresh.configs.vite,
  prettierConfig,  // 放最后
];

总结

ESLint 解决的核心问题:让错误尽早暴露、让风格保持一致、让最佳实践成为习惯。

不用 ESLint 用 ESLint
Bug 到运行时才暴露 写代码时就发现
Code Review 在争论分号 Code Review 聚焦逻辑
每个人代码风格不同 团队代码如同出自一人
新人不了解最佳实践 规则本身就是文档和教学

如果你还没在项目里用 ESLint,现在就装一个吧:

bash 复制代码
npm install -D eslint
npx eslint --init

你的代码库会感谢你。

相关推荐
嘻哈∠※1 小时前
0061基于 SpringBoot 的投稿与稿件处理系统设计与实现
java·spring boot·后端
卷无止境1 小时前
在 awesome-fastapi 里,哪些库值得一看?
后端·python
圣殿骑士-Khtangc2 小时前
Go字符串高效拼接性能对比与底层原理分析
服务器·前端·golang
卷无止境2 小时前
FastAPI 的Admin面板生态
后端·python
BigTopOne3 小时前
【ijkplayer】 硬解码流程
前端
kyriewen3 小时前
DeepSeek Harness开源第一天我就上手了——和Claude Code的差距比想象中大
前端·ai编程·deepseek
捡田螺的小男孩4 小时前
什么是 Skill?手把手带你写一个简单有用的 Skill!
前端·后端·程序员
IT_陈寒4 小时前
Redis集群这个坑,差点让我通宵
前端·人工智能·后端
90后的晨仔4 小时前
uni-app 路由跳转与页面导航 —— 终极详解(对标 iOS / Android / 鸿蒙三端原生)
前端