小白总结的译文,出自《AST for JavaScript developers》
为什么要谈AST
如果你查看目前任何主流的项目中的 devDependencies
,会发现这些年不计其数的插件诞生。我们归纳一下有:javascript转译、代码压缩、css预处理器、elint、pretiier
等。有很多js模块不会在生产环境用到,但是它们在开发过程中充当着重要的角色。所有的上述工具,不管怎样,都建立在了AST
这个巨人的肩膀上。

什么是AST
官方定义:It 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.

这很简化,只是大体思想。实际上,真正AST每个节点会有更多的信息。从纯文本中,我们将得到树形结构的数据。每个条目和树中的节点一一对应。
如何生成AST
那怎么从纯文本中得到AST呢?我们知道当下的编译器都做了这件事情。

幸运的是,我们无需贯穿编译器的所有知识点,最后将高级语言转译为二进制代码。只需要关注词法分析和语法分析,这两步是从代码中生成AST的关键所在。
- 词法分析
也叫做扫描Scanner
。它读取我们的代码,然后把它们按照预定的规则合并成一个个的标识tokens
。同时,它会移除空白符、注释 等。最后,整个代码将被分割进一个tokens
列表(或者说一维数组)。

当词法分析源代码时,它会一个一个字母地读取代码,所以很形象地称之为扫描-scans
;当它遇到空格,操作符,或者特殊符号时,会认为一个话已经完成了。
- 语法分析
即解析器。它会将词法分析出来的数组转化成树形的表达形式。同时验证语法,语法如果有错的话,抛出语法错误。

当生成树时,解析器会删除一些没必要的标识tokens
(比如不完整的括号),因此AST
不是100%
与源码匹配的,但已经能让我们知道如何处理了。说个题外话,解析器100%
覆盖所有代码结构生成树叫做CST(具体语法树)
- 生成AST结构

玩转AST
astexplorer 是一个很棒的网站,可以在线玩转AST,其中包含了很多第三方AST库。除了JS,还有很多其他语言的AST库。
- babylon
babylon
是一个很棒的第三方库,它被用在大名鼎鼎的babel
中,一直支持最新的JS特性,不用担心以后JS又出新版导致代码大规模重构。 - babel
Babel is not a ‘tool for having ES6 support’. Well, it is, but it is far not only what it is about.
经常把beble
和支持es6/7/8
联系起来,但它仅仅是一组插件中的一个。我们也可以使用它来压缩代码、react
相关语法转译(如jsx
)、flow
插件 等。
babel
是一个Javascript
编译器。宏观来说,它分3个阶段运行代码:解析parsing --> 转译transforming --> 生成generation
。我们可以给babel
一些Javascript
代码,它修改代码,然后生成新的代码返回。
那babel
是怎样修改代码的呢?没错!它创建了AST
,遍历树,修改tokens
,最后从AST
中生成新的代码。
范例

babel
使用babylon
-->
首先解析代码成AST
,然后遍历AST
,再反转所有的变量名,最后生成代码!
正如我们看到的,第一步(解析)和第三步(生成)看起来非常常规,我们每次都会做这两步。所以,babel
接管处理了它们。最后,我们最为关心的,那就是AST
转译这一步了。
当我们开发babel-plugin
时,只需要描述转化AST
的节点visitors
就可以了

将它加入babel
插件列表中,设置webpack
的babel-loader
配置 或者 .babelrc
中的plugins
即可。
- JScodeshift
比如你想要替换掉所有老掉牙的匿名函数,把它们变成Lambda
表达式(箭头函数)。

这时候jscodeshift
就登场了,jscodeshift
是一个跑codemods
的工具,codemods
是一段描述AST要转化成什么样的代码,思想和babel
的插件如出一辙。

所以,如果你想创建自动把你的代码从旧的框架迁移到新的框架,这就是一种很nice
的方式
比如 react 16
的 prop-types
重构

有很多不同的codemodes已经创建了:
https://github.com/facebook/jscodeshift
https://github.com/reactjs/react-codemod
- Prettier

Prettier
格式化我们的代码,调整长句,整理空格,括号等。所以它将代码作为输入,修改后的代码作为输出。听起来很熟悉对吧!

思路还是一样。首先,将代码生成AST
。之后依然是处理AST
,最后生成代码。但是,中间过程其实并不像它看起来那么简单。
网友评论