<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          手把手教你 ESLint

          共 13295字,需瀏覽 27分鐘

           ·

          2020-09-10 16:23

          前言

          小沈是一個剛剛開始工作的前端實習生,第一次進行團隊開發(fā),難免有些緊張。在導師的安排下,拿到了項目的 git 權限,開始進行 clone。

          $?git?clone[email protected]:company/project.git

          小沈開始細細品味著同事們的代碼,終于在他的不懈努力下,發(fā)現(xiàn)了老王 2 年前寫的一個 bug,跟導師報備之后,小沈開始著手修改。年輕人嘛,容易沖動,不僅修復了老王的 bug,還把這部分代碼進行了重構,使用了前兩天剛剛從書里學會的策略模式,去掉了一些不必要 if else 邏輯。小沈瀟灑的摸了摸自己稀疏的頭發(fā),得意的準備提交代碼,想著第一天剛來就秀了下自己的超強的編碼能力。接下來可怕的事情發(fā)生了,代碼死活不能通過 lint 工具的檢測,急得他面紅耳赤,趕緊跑去問導師,導師告訴他,只要按照控制臺的 warning 修改代碼就好。小沈反駁道,這個 lint 工具非讓我去掉分號,我在學校的時候,老師就教我分號是必不可少的,沒有分號的代碼是不完美的。導師無奈的笑了笑,打開了小沈的實習評分表,在團隊合作一項中勾選『較差』。

          不服氣的小沈,寫了一篇博客發(fā)布到了 CSDN 上,還收獲了不少閱讀量。

          image

          問:工作第一天小沈犯了哪些錯誤?

          1. 對不了解的業(yè)務代碼進行重構,這是業(yè)務開發(fā)的大忌;
          2. 沒有遵守團隊規(guī)范,團隊開發(fā)帶有太強的個人情緒;
          3. 上面都是我編的,聽說現(xiàn)在寫文章開頭都要編個故事。

          lint 工具簡史

          在計算機科學中,lint是一種工具的名稱,它用來標記代碼中,某些可疑的、不具結構性(可能造成bug)的語句。它是一種靜態(tài)程序分析工具,最早適用于C語言,在UNIX平臺上開發(fā)出來。后來它成為通用術語,可用于描述在任何一種編程語言中,用來標記代碼中有疑義語句的工具。? ?-- by wikipedia

          在 JavaScript 20 多年的發(fā)展歷程中,也出現(xiàn)過許許多多的 lint 工具,下面就來介紹下主流的三款 lint 工具。

          1. JSLint
          2. JSHint
          3. ESLint
          image

          JSLint

          JSLint logo

          JSLint 可以說是最早出現(xiàn)的 JavaScript 的 lint 工具,由 Douglas Crockford (《JavaScript 語言精粹》作者) 開發(fā)。從《JavaScript 語言精粹》的筆風就能看出,Douglas 是個眼里容不得瑕疵的人,所以 JSLint 也繼承了這個特色,JSLint 的所有規(guī)則都是由 Douglas 自己定義的,可以說這是一個極具 Douglas 個人風格的 lint 工具,如果你要使用它,就必須接受它所有規(guī)則。值得稱贊的是,JSLint 依然在更新,而且也提供了 node 版本:node-jslint。

          JSHint

          JSHint logo

          由于 JSLint 讓很多人無法忍受它的規(guī)則,感覺受到了壓迫,所以 Anton Kovalyov (現(xiàn)在在 Medium 工作) 基于 JSLint 開發(fā)了 JSHint,。JSHint 在 JSLint 的基礎上提供了豐富的配置項,給了開發(fā)者極大的自由,JSHint 一開始就保持著開源軟件的風格,由社區(qū)進行驅動,發(fā)展十分迅速。早期?jQuery 也是使用 JSHint 進行代碼檢查的,不過現(xiàn)在已經(jīng)轉移到 ESLint 了。

          ESLint

          ESLint logo

          ESLint 由 Nicholas C. Zakas (《JavaScript 高級程序設計》作者) 于2013年6月創(chuàng)建,它的出現(xiàn)因為 Zakas 想使用 JSHint 添加一條自定義的規(guī)則,但是發(fā)現(xiàn) JSHint 不支持,于是乎自己開發(fā)了一個。

          ESLint 號稱下一代的 JS Linter 工具,它的靈感來源于 PHP Linter,將源代碼解析成 AST,然后檢測 AST 來判斷代碼是否符合規(guī)則。ESLint 使用 esprima 將源代碼解析成 AST,然后你就可以使用任意規(guī)則來檢測 AST 是否符合預期,這也是 ESLint 高可擴展性的原因。

          早期源碼:

          var?ast?=?esprima.parse(text,?{?loc:?true,?range:?true?}),
          ????walk?=?astw(ast);

          walk(function(node)?{
          ????api.emit(node.type,?node);
          });

          return?messages;

          但是,那個時候 ESLint 并沒有大火,因為需要將源代碼轉成 AST,運行速度上輸給了 JSHint ,并且 JSHint 當時已經(jīng)有完善的生態(tài)(編輯器的支持)。真正讓 ESLint 大火是因為 ES6 的出現(xiàn)。

          ES6 發(fā)布后,因為新增了很多語法,JSHint 短期內無法提供支持,而 ESLint 只需要有合適的解析器就能夠進行 lint 檢查。這時 babel 為 ESLint 提供了支持,開發(fā)了 babel-eslint,讓ESLint 成為最快支持 ES6 語法的 lint 工具。

          谷歌趨勢

          在 2016 年,ESLint整合了與它同時誕生的另一個 lint 工具:JSCS,因為它與 ESLint 具有異曲同工之妙,都是通過生成 AST 的方式進行規(guī)則檢測。

          ESLint整合JSCS

          自此,ESLint 在 JS Linter 領域一統(tǒng)江湖,成為前端界的主流工具。

          Lint 工具的意義

          下面一起來思考一個問題:Lint 工具對工程師來說到底是代碼質量的保證還是一種束縛?

          然后,我們再看看 ESLint 官網(wǎng)的簡介:

          代碼檢查是一種靜態(tài)的分析,常用于尋找有問題的模式或者代碼,并且不依賴于具體的編碼風格。對大多數(shù)編程語言來說都會有代碼檢查,一般來說編譯程序會內置檢查工具。

          JavaScript 是一個動態(tài)的弱類型語言,在開發(fā)中比較容易出錯。因為沒有編譯程序,為了尋找 JavaScript 代碼錯誤通常需要在執(zhí)行過程中不斷調試。像 ESLint 這樣的可以讓程序員在編碼的過程中發(fā)現(xiàn)問題而不是在執(zhí)行的過程中。

          因為 JavaScript 這門神奇的語言,在帶給我們靈活性的同時,也埋下了一些坑。比如 == 涉及到的弱類型轉換,著實讓人很苦惱,還有 this 的指向,也是一個讓人迷惑的東西。而 Lint 工具就很好的解決了這個問題,干脆禁止你使用 == ,這種做法雖然限制了語言的靈活性,但是帶來的收益也是可觀的。

          還有就是作為一門動態(tài)語言,因為缺少編譯過程,有些本可以在編譯過程中發(fā)現(xiàn)的錯誤,只能等到運行才發(fā)現(xiàn),這給我們調試工作增加了一些負擔,而 Lint 工具相當于為語言增加了編譯過程,在代碼運行前進行靜態(tài)分析找到出錯的地方。

          所以匯總一下,Lint工具的優(yōu)勢:

          1. 避免低級bug,找出可能發(fā)生的語法錯誤

          使用未聲明變量、修改 const 變量……

          2. 提示刪除多余的代碼

          聲明而未使用的變量、重復的 case ……

          3. 確保代碼遵循最佳實踐

          可參考 airbnb style、javascript standard

          4. 統(tǒng)一團隊的代碼風格

          加不加分號?使用 tab 還是空格?

          使用方式

          說了那么多,還是來看下有點實際意義的,ESLint 到底是如何使用的。

          初始化

          如果想在現(xiàn)有項目中引入 ESLint,可以直接運行下面的命令:

          #?全局安裝?ESLint
          $?npm?install?-g?eslint

          #?進入項目
          $?cd?~/Code/ESLint-demo

          #?初始化?package.json
          $?npm?init?-f

          #?初始化?ESLint?配置
          $?eslint?--init
          image

          在使用 eslint --init 后,會出現(xiàn)很多用戶配置項,具體可以參考:eslint cli 部分的源碼。

          經(jīng)過一系列一問一答的環(huán)節(jié)后,你會發(fā)現(xiàn)在你文件夾的根目錄生成了一個 .eslintrc.js 文件。

          image

          配置方式

          ESLint 一共有兩種配置方式:

          1. 使用注釋把 lint 規(guī)則直接嵌入到源代碼中

          這是最簡單粗暴的方式,直接在源代碼中使用 ESLint 能夠識別的注釋方式,進行 lint 規(guī)則的定義。

          /*?eslint?eqeqeq:?"error"?*/
          var?num?=?1
          num?==?'1'
          image

          當然我們一般使用注釋是為了臨時禁止某些嚴格的 lint 規(guī)則出現(xiàn)的警告:

          /*?eslint-disable?*/
          alert('該注釋放在文件頂部,整個文件都不會出現(xiàn)?lint?警告')

          /*?eslint-enable?*/
          alert('重新啟用?lint?告警')

          /*?eslint-disable?eqeqeq?*/
          alert('只禁止某一個或多個規(guī)則')

          /*?eslint-disable-next-line?*/
          alert('當前行禁止?lint?警告')

          alert('當前行禁止?lint?警告')?//?eslint-disable-line

          2. 使用配置文件進行 lint 規(guī)則配置

          在初始化過程中,有一個選項就是使用什么文件類型進行 lint 配置(What format do you want your config file to be in?):

          {
          ????type:?"list",
          ????name:?"format",
          ????message:?"What?format?do?you?want?your?config?file?to?be?in?",
          ????default:?"JavaScript",
          ????choices:?["JavaScript",?"YAML",?"JSON"]
          }

          官方一共提供了三個選項:

          1. JavaScript (eslintrc.js)
          2. YAML (eslintrc.yaml)
          3. JSON (eslintrc.json)

          另外,你也可以自己在 package.json 文件中添加 eslintConfig 字段進行配置。

          翻閱 ESLint 源碼可以看到,其配置文件的優(yōu)先級如下:

          const?configFilenames?=?[
          ??".eslintrc.js",
          ??".eslintrc.yaml",
          ??".eslintrc.yml",
          ??".eslintrc.json",
          ??".eslintrc",
          ??"package.json"
          ];

          當然你也可以使用 cli 自己指定配置文件路徑:

          image

          項目級與目錄級的配置

          我們有如下目錄結構,此時在根目錄運行 ESLint,那么我們將得到兩個配置文件 .eslintrc.js(項目級配置) 和 src/.eslintrc.js(目錄級配置),這兩個配置文件會進行合并,但是 src/.eslintrc.js 具有更高的優(yōu)先級。

          目錄結構

          但是,我們只要在 src/.eslintrc.js 中配置 "root": true,那么 ESLint 就會認為 src 目錄為根目錄,不再向上查找配置。

          {
          ??"root":?true
          }

          配置參數(shù)

          下面我們一起來細細品味 ESLinte 的配置規(guī)則。

          解析器配置

          {
          ??//?解析器類型
          ??//?espima(默認),?babel-eslint,?@typescript-eslint/parse
          ??"parse":?"esprima",
          ??//?解析器配置參數(shù)
          ??"parseOptions":?{
          ????//?代碼類型:script(默認), module
          ????"sourceType":?"script",
          ????// es 版本號,默認為 5,也可以使用年份,比如 2015 (同 6)
          ????"ecamVersion":?6,
          ????//?es?特性配置
          ????"ecmaFeatures":?{
          ????????"globalReturn":?true,?//?允許在全局作用域下使用?return?語句
          ????????"impliedStrict":?true,?//?啟用全局?strict?mode?
          ????????"jsx":?true?//?啟用?JSX
          ????},
          ??}
          }

          對于 @typescript-eslint/parse 這個解析器,主要是為了替代之前存在的 TSLint,TS 團隊因為 ESLint 生態(tài)的繁榮,且 ESLint 具有更多的配置項,不得不拋棄 TSLint 轉而實現(xiàn)一個 ESLint 的解析器。同時,該解析器擁有不同的配置:

          {
          ??"parserOptions":?{
          ????"ecmaFeatures":?{
          ??????"jsx":?true
          ????},
          ????"useJSXTextNode":?true,
          ????"project":?"./tsconfig.json",
          ????"tsconfigRootDir":?"../../",
          ????"extraFileExtensions":?[".vue"]
          ??}
          }

          環(huán)境與全局變量

          ESLint 會檢測未聲明的變量,并發(fā)出警告,但是有些變量是我們引入的庫聲明的,這里就需要提前在配置中聲明。

          {
          ??"globals":?{
          ????//?聲明?jQuery?對象為全局變量
          ????"$":?false?//?true表示該變量為?writeable,而?false?表示?readonly
          ??}
          }

          globals 中一個個的進行聲明未免有點繁瑣,這個時候就需要使用到 env ,這是對一個環(huán)境定義的一組全局變量的預設(類似于 babel 的 presets)。

          {
          ??"env":?{
          ????"amd":?true,
          ????"commonjs":?true,
          ????"jquery":?true
          ??}
          }

          可選的環(huán)境很多,預設值都在這個文件中進行定義,查看源碼可以發(fā)現(xiàn),其預設變量都引用自 globals 包。

          env
          env

          規(guī)則設置

          ESLint 附帶有大量的規(guī)則,你可以在配置文件的 rules 屬性中配置你想要的規(guī)則。每一條規(guī)則接受一個參數(shù),參數(shù)的值如下:

          • "off" 或 0:關閉規(guī)則
          • "warn" 或 1:開啟規(guī)則,warn 級別的錯誤 (不會導致程序退出)
          • "error" 或 2:開啟規(guī)則,error級別的錯誤(當被觸發(fā)的時候,程序會退出)

          舉個例子,我們先寫一段使用了平等(equality)的代碼,然后對 eqeqeq 規(guī)則分別進行不同的配置。

          //?demo.js
          var?num?=?1
          num?==?'1'
          eqeqeq 規(guī)則校驗

          這里使用了命令行的配置方式,如果你只想對單個文件進行某個規(guī)則的校驗就可以使用這種方式。

          但是,事情往往沒有我們想象中那么簡單,ESLint 的規(guī)則不僅只有關閉和開啟這么簡單,每一條規(guī)則還有自己的配置項。如果需要對某個規(guī)則進行配置,就需要使用數(shù)組形式的參數(shù)。

          我們看下 quotes 規(guī)則,根據(jù)官網(wǎng)介紹,它支持字符串和對象兩個配置項。

          quotes
          {
          ??"rules":?{
          ????//?使用數(shù)組形式,對規(guī)則進行配置
          ????//?第一個參數(shù)為是否啟用規(guī)則
          ????//?后面的參數(shù)才是規(guī)則的配置項
          ????"quotes":?[
          ??????"error",
          ??????"single",
          ??????{
          ????????"avoidEscape":?true?
          ??????}
          ????]
          ??}
          }

          根據(jù)上面的規(guī)則:

          //?bad
          var?str?=?"test?'ESLint'?rule"

          //?good
          var?str?=?'test?"ESLint"?rule'

          擴展

          擴展就是直接使用別人已經(jīng)寫好的 lint 規(guī)則,方便快捷。擴展一般支持三種類型:

          {
          ??"extends":?[
          ????"eslint:recommended",
          ????"plugin:react/recommended",
          ????"eslint-config-standard",
          ??]
          }
          • eslint: 開頭的是 ESLint 官方的擴展,一共有兩個:eslint:recommendedeslint:all
          • plugin: 開頭的是擴展是插件類型,也可以直接在 plugins 屬性中進行設置,后面一節(jié)會詳細講到。
          • 最后一種擴展來自 npm 包,官方規(guī)定 npm 包的擴展必須以 eslint-config- 開頭,使用時可以省略這個頭,上面案例中 eslint-config-standard 可以直接簡寫成 standard

          如果你覺得自己的配置十分滿意,也可以將自己的 lint 配置發(fā)布到 npm 包,只要將包名命名為 eslint-config-xxx 即可,同時,需要在 package.json 的 peerDependencies 字段中聲明你依賴的 ESLint 的版本號。

          插件

          使用插件

          雖然官方提供了上百種的規(guī)則可供選擇,但是這還不夠,因為官方的規(guī)則只能檢查標準的 JavaScript 語法,如果你寫的是 JSX 或者 Vue 單文件組件,ESLint 的規(guī)則就開始束手無策了。

          這個時候就需要安裝 ESLint 的插件,來定制一些特定的規(guī)則進行檢查。ESLint 的插件與擴展一樣有固定的命名格式,以 eslint-plugin- 開頭,使用的時候也可以省略這個頭。

          npm?install?--save-dev?eslint-plugin-vue?eslint-plugin-react
          {
          ??"plugins":?[
          ????"react",?//?eslint-plugin-react
          ????"vue",???//?eslint-plugin-vue
          ??]
          }

          或者是在擴展中引入插件,前面有提到 plugin: 開頭的是擴展是進行插件的加載。

          {
          ??"extends":?[
          ????"plugin:react/recommended",
          ??]
          }

          通過擴展的方式加載插件的規(guī)則如下:

          extPlugin?=?`plugin:${pluginName}/${configName}`

          對照上面的案例,插件名(pluginName) 為 react,也就是之前安裝 eslint-plugin-react 包,配置名(configName)為 recommended。那么這個配置名又是從哪里來的呢?

          可以看到 eslint-plugin-react 的源碼。

          module.exports?=?{
          ??//?自定義的?rule
          ??rules:?allRules,
          ??//?可用的擴展
          ??configs:?{
          ????//?plugin:react/recommended
          ????recomended:?{
          ??????plugins:?[?'react'?]
          ??????rules:?{...}
          ????},
          ????//?plugin:react/all
          ????all:?{
          ??????plugins:?[?'react'?]
          ??????rules:?{...}
          ????}
          ??}
          }

          配置名是插件配置的 configs 屬性定義的,這里的配置其實就是 ESLint 的擴展,通過這種方式即可以加載插件,又可以加載擴展。

          開發(fā)插件

          ESLint 官方為了方便開發(fā)者,提供了 Yeoman 的模板(generator-eslint)。

          #?安裝模塊
          npm?install?-g?yo?generator-eslint

          #?創(chuàng)建目錄
          mkdir?eslint-plugin-demo
          cd?eslint-plugin-demo

          #?創(chuàng)建模板
          yo?eslint:plugin
          eslint:plugin
          eslint:plugin 目錄

          創(chuàng)建好項目之后,就可以開始創(chuàng)建一條規(guī)則了,幸運的是 generator-eslint 除了能夠生成插件的模板代碼外,還具有創(chuàng)建規(guī)則的模板代碼。打開之前創(chuàng)建的 eslint-plugin-demo 文件夾,在該目錄下添加一條規(guī)則,我希望這條規(guī)則能檢測出我的代碼里面是否有 console ,所以,我給該規(guī)則命名為 disable-console

          yo?eslint:rule
          eslint:rule
          eslint:rule 目錄

          接下來我們看看如何來指定 ESLinte 的一個規(guī)則:

          打開 lib/rules/disable-console.js ,可以看到默認的模板代碼如下:

          module.exports?=?{
          ??meta:?{
          ????docs:?{
          ??????description:?"disable?console",
          ??????category:?"Fill?me?in",
          ??????recommended:?false
          ????},
          ????schema:?[]
          ??},
          ??create:?function?(context)?{
          ????//?variables?should?be?defined?here
          ????return?{
          ??????//?give?me?methods
          ????};
          ??}
          };

          簡單的介紹下其中的參數(shù)(更詳細的介紹可以查看官方文檔):

          • meta:規(guī)則的一些描述信息
            • descrition(string):規(guī)則的簡短描述
            • category(string):規(guī)則的類別(具體類別可以查看官網(wǎng))
            • recommended(boolean):是否加入 eslint:recommended
            • docs:規(guī)則的描述對象
            • schema(array):規(guī)則所接受的配置項
          • create:返回一個對象,該對象包含 ESLint 在遍歷 JavaScript 代碼 AST 時,所觸發(fā)的一系列事件勾子。

          在詳細講解如何創(chuàng)建一個規(guī)則之前,我們先來談談 AST(抽象語法樹)。ESLint 使用了一個叫做 Espree 的 JavaScript 解析器來把 JavaScript 代碼解析為一個 AST 。然后深度遍歷 AST,每條規(guī)則都會對匹配的過程進行監(jiān)聽,每當匹配到一個類型,相應的規(guī)則就會進行檢查。為了方便查看 AST 的各個節(jié)點類型,這里提供一個網(wǎng)站能十分清晰的查看一段代碼解析成 AST 之后的樣子:astexplorer。如果你想找到所有 AST 節(jié)點的類型,可以查看 estree。

          astexplorer
          astexplorer

          可以看到 console.log() 屬于 ExpressionStatement(表達式語句) 中的 CallExpression(調用語句)

          {
          ??"type":?"ExpressionStatement",
          ??"expression":?{
          ????"type":?"CallExpression",
          ????"callee":?{
          ??????"type":?"MemberExpression",
          ??????"object":?{
          ????????"type":?"Identifier",
          ????????"name":?"console"
          ??????},
          ??????"property":?{
          ????????"type":?"Identifier",
          ????????"name":?"log"
          ??????},
          ??????"computed":?false
          ????}
          ??}
          }

          所以,我們要判斷代碼中是否調用了 console,可以在 create 方法返回的對象中,寫一個 CallExpression 方法,在 ESLint 遍歷 AST 的過程中,對調用語句進行監(jiān)聽,然后檢查該調用語句是否為 console 調用。

          module.exports?=?{
          ??create:?function(context)?{
          ????return?{
          ??????CallExpression(node)?{
          ????????//?獲取調用語句的調用對象
          ????????const?callObj?=?node.callee.object
          ????????if?(!callObj)?{
          ??????????return
          ????????}
          ????????if?(callObj.name?!==?'console')?{
          ??????????//?如果調用對象為?console,通知?ESLint
          ??????????context.report({
          ????????????node,
          ????????????message:?'error:?should?remove?console'
          ??????????})
          ????????}
          ??????},
          ????}
          ??}
          }

          可以看到我們最后通過 context.report 方法,告訴 ESLint 這是一段有問的代碼,具體要怎么處理,就要看 ESLint 配置中,該條規(guī)則是 [off, warn, error] 中的哪一個了。

          之前介紹規(guī)則的時候,有講到規(guī)則是可以接受配置的,下面看看我們自己制定規(guī)則的時候,要如何接受配置項。其實很簡單,只需要在 mate 對象的 schema 中定義好參數(shù)的類型,然后在 create 方法中,通過 context.options 獲取即可。下面對 disable-console 進行修改,畢竟禁止所有的 console 太過嚴格,我們可以添加一個參數(shù),該參數(shù)是一個數(shù)組,表示允許調用的 console 方法。

          module.exports?=?{
          ??meta:?{
          ????docs:?{
          ??????description:?"disable?console",?//?規(guī)則描述
          ??????category:?"Possible?Errors",????//?規(guī)則類別
          ??????recommended:?false
          ????},
          ????schema:?[?//?接受一個參數(shù)
          ??????{
          ????????type:?'array',?//?接受參數(shù)類型為數(shù)組
          ????????items:?{
          ??????????type:?'string'?//?數(shù)組的每一項為一個字符串
          ????????}
          ??????}
          ????]
          ??},

          ??create:?function(context)?{
          ????const?logs?=?[?//?console?的所以方法
          ????????"debug",?"error",?"info",?"log",?"warn",?
          ????????"dir",?"dirxml",?"table",?"trace",?
          ????????"group",?"groupCollapsed",?"groupEnd",?
          ????????"clear",?"count",?"countReset",?"assert",?
          ????????"profile",?"profileEnd",?
          ????????"time",?"timeLog",?"timeEnd",?"timeStamp",?
          ????????"context",?"memory"
          ????]
          ????return?{
          ??????CallExpression(node)?{
          ?????????//?接受的參數(shù)
          ????????const?allowLogs?=?context.options[0]
          ????????const?disableLogs?=?Array.isArray(allowLogs)
          ??????????//?過濾掉允許調用的方法
          ????????????logs.filter(log?=>?!allowLogs.includes(log))
          ??????????:?logs
          ????????const?callObj?=?node.callee.object
          ????????const?callProp?=?node.callee.property
          ????????if?(!callObj?||?!callProp)?{
          ??????????return
          ????????}
          ????????if?(callObj.name?!==?'console')?{
          ??????????return
          ????????}
          ????????//?檢測掉不允許調用的?console?方法
          ????????if?(disableLogs.includes(callProp.name))?{
          ??????????context.report({
          ????????????node,
          ????????????message:?'error:?should?remove?console'
          ??????????})
          ????????}
          ??????},
          ????}
          ??}
          }

          規(guī)則寫完之后,打開 tests/rules/disable-console.js ,編寫測試用例。

          var?rule?=?require("../../../lib/rules/disable-console")
          var?RuleTester?=?require("eslint").RuleTester

          var?ruleTester?=?new?RuleTester()
          ruleTester.run("disable-console",?rule,?{
          ??valid:?[{
          ????code:?"console.info(test)",
          ????options:?[['info']]
          ??}],
          ??invalid:?[{
          ????code:?"console.log(test)",
          ????errors:?[{?message:?"error:?should?remove?console"?}]
          ??}]
          });
          test

          最后,只需要引入插件,然后開啟規(guī)則即可。

          //?eslintrc.js
          module.exports?=?{
          ??plugins:?[?'demo'?],
          ??rules:?{
          ????'demo/disable-console':?[
          ??????'error',?[?'info'?]
          ????],
          ??}
          }
          use plugin demo

          最佳配置

          最佳配置

          業(yè)界有許多 JavaScript 的推薦編碼規(guī)范,較為出名的就是下面兩個:

          1. airbnb style
          2. javascript standard

          同時這里也推薦 AlloyTeam 的 eslint-config-alloy。

          但是代碼規(guī)范這個東西,最好是團隊成員之間一起來制定,確保大家都能夠接受,如果實在是有人有異議,就只能少數(shù)服從多數(shù)了。雖然這節(jié)的標題叫最佳配置,但是軟件行業(yè)并有沒有什么方案是最佳方案,即使 javascript standard 也不是 javascript 標準的編碼規(guī)范,它僅僅只是叫這個名字而已,只有適合的才是最好的。

          最后安利一下,將 ESLint 和 Prettier 結合使用,不僅統(tǒng)一編碼規(guī)范,也能統(tǒng)一代碼風格。具體實踐方式,請參考我的文章:使用ESLint+Prettier來統(tǒng)一前端代碼風格。

          總結

          看到這里我們做一個總結,JavaScript 的 linter 工具發(fā)展歷史其實也不算短,ESLint 之所以能夠后來者居上,主要原因還是 JSLint 和 JSHint 采用自頂向下的方式來解析代碼,并且早期 JavaScript 語法萬年不更新,能這種方式夠以較快的速度來解析代碼,找到可能存在的語法錯誤和不規(guī)范的代碼。但是 ES6 發(fā)布之后,JavaScript 語法發(fā)生了很多的改動,比如:箭頭函數(shù)、模板字符串、擴展運算符……,這些語法的發(fā)布,導致 JSLint 和 JSHint 如果不更新解析器就沒法檢測 ES6 的代碼。而 ESLint 另辟蹊徑,采用 AST 的方式對代碼進行靜態(tài)分析,并保留了強大的可擴展性和靈活的配置能力。這也告訴我們,在日常的編碼過程中,一定要考慮到后續(xù)的擴展能力。

          正是因為這個強大擴展能力,讓業(yè)界的很多 JavaScript 編碼規(guī)范能夠在各個團隊進行快速的落地,并且團隊自己定制的代碼規(guī)范也可以對外共享。

          最后,希望你通過上面的學習已經(jīng)理解了 ESLint 帶來的好處,同時掌握了 ESLint 的用法,并可以為現(xiàn)有的項目引入 ESLint 改善項目的代碼質量。

          參考

          • ESLint 官網(wǎng)
          • JS Linter 進化史
          • ESLint 工作原理探討




          推薦閱讀




          我的公眾號能帶來什么價值?(文末有送書規(guī)則,一定要看)

          每個前端工程師都應該了解的圖片知識(長文建議收藏)

          為什么現(xiàn)在面試總是面試造火箭?

          瀏覽 58
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产日本在线观看 | 无码在线观看网 | 国产老熟女一区二区三区 | 国产日产久久高清欧美 | 国产小黄片 |