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进阶 」,一块儿学习。