AST 是很是有用的
。javascript
今天下午聽了小組一個老哥作的AST分享,深覺得然。前端
爲了加深印象,就寫了篇總結,順便分享給你們,但願能給朋友們一些啓發。java
AST有用,口說無憑, 且看幾個具體的案例
。node
且不說:react
Vue => React
React => Vue
的代碼轉換方法,git
咱們就看一個能夠無痛升級舊版React
的工具:github
react-codemod
npm
代碼地址:https://github.com/reactjs/re...segmentfault
這個工具,功能十分強大,使用起來也很方便,只須要運行一行命令:api
npx react-codemod <transform> <path> [...options]
這些無不借助了AST。
下面咱們就進入今天的內容。
本文的主要內容包括:
var
轉換成let
AST is a hierarchical program representation that presents source code structure according to the grammar of a programming language, each AST node corresponds to an item of a source code.
在計算機科學中,抽象語法
和抽象語法樹
實際上是源代碼的抽象語法結構的樹狀表現形式
。
經常使用的瀏覽器就是經過將js代碼轉化爲抽象語法樹來進行下一步的分析等其餘操做。
因此將js轉化爲抽象語法樹更利於程序的分析。
爲了便於理解, 咱們看一個具體的例子。
這裏順便給你們介紹一個十分有用的網站: https://astexplorer.net/
你譬如:
聲明, 變量, 類型等各類信息包羅萬象。
並且這裏也提供了各類插件模版供你選擇:
十分的方便。
咱們就根據這個例子, 咱們作個小的實踐。
好比, 如今要重構一個老項目, 你要把項目裏的var 所有替換成let, 你會怎麼作?
手動替換?
或者藉助工具一鍵替換?
如今就教你一招:一鍵替換大法
。
首先仍是要介紹一把大殺器: jscodeshift
jscodeshift 是一個 Javscript Codemod 工具,官方對 Codemod 的解釋是:
Codemod is a tool/library to assist you with large-scale codebase refactors that can be partially automated but still require human oversight and occasional intervention.
jscodeshift 也是基於 esprima
的,其經過 path 能夠很容易的在 AST 上遍歷 node
。
如今咱們就開始替換項目中的var.
首先,到 https://astexplorer.net 裏面編寫代碼.
模板咱們選: jscodeshift
官方自帶的例子, 把變量名字反轉:
咱們如今要改變量, 這個工具很貼心的一點是能夠高亮實時對照,
如今, 找到kind === var
的對象, 替換成let
:
獲得以下代碼:
export default function transformer(file, api) { const j = api.jscodeshift; return j(file.source) .find(j.VariableDeclaration, { kind: 'var'}) .forEach(path => { const letStatement = j.variableDeclaration('let', path.node.declarations) j(path).replaceWith(letStatement) }) .toSource(); }
這樣也能夠:
path.node.kind = 'let'; // 傳入的實際是一個引用
實際效果:
大功告成!
假如我項目裏有幾個文件也須要相同的操做:
簡單安裝:
sudo npm install -g jscodeshift
執行:
jscodeshift -t transform.js ./src/demo.js --dry --print
這裏用了--dry 和 --print
--dry
加上以後,不會馬上把新生成的代碼覆蓋源文件
--print
是打印出來看看
在實際項目裏, 你須要在獨立的分支裏
操做,新生成代碼以後, 須要你再檢查檢查
, review沒有問題
以後才能合併。
和上面的相似, 咱們也能夠作一個eslint 插件, 功能也很簡單: 檢查到使用console的時候就報錯
。
指望達到的效果:
// Do not use console methods (at 1:9) console.log('haha') // --------^
咱們此次選擇 babel-eslint
模版。
代碼實現:
const disallowMethods = ["log", "info", "warn", "error", "dir"]; export default function(context) { return { Identifier(node) { const isConsoleMethod = disallowMethods.includes(node.name) && node.parent.type === "MemberExpression" && node.parent.object.name === "console"; if (!isConsoleMethod) return; context.report({ node, message: "Do not use console methods" }); } }; }
實際效果:
簡單有效。
不過你要是非要玩什麼騷操做,好比自定義一個log, 那就沒得搞了。
最後, 你能夠把這段代碼封裝成一個完整的插件:
你能夠自行實踐。
最後一個是過濾源代碼中的debugger, Transform 咱們選擇babelv7
這個插件,咱們指望達到的效果是:
var a = 1 debugger function test() { debugger a++ } debugger
到:
var a = 1; function test() { a++; }
這也是一個十分有用的功能。
代碼實現:
export default function (babel) { const { types: t } = babel; return { name: "ast-transform", // not required visitor: { DebuggerStatement(path) { path.remove() } } }; }
實際效果:
內容大概就是這麼多,沒什麼難度,重在講述理論和入門
。
對AST還不熟練的同窗, 但願這篇能夠幫助到你。
後面還有會AST在咱們實際項目中的應用
, 我也會寫一個實戰篇
, 敬請期待!
以上。
https://www.toptal.com/javasc...
若是以爲內容有幫助,能夠關注下個人公衆號 「 前端e進階 」,一塊兒學習。