AST 抽象语法树

507 阅读3分钟

前言:

Q1:AST是什么?如何得到AST?

Q2:AST用处是什么?

Q1:AST是什么?如何得到AST?

在程序中,一段代码在被执行之前,都会经历三个阶段:

1.扫描--词法分析

这个过程会将由字符组成的字符串分解成有意义的代码块,称为词法单元tokens。 例如 var a = 4;会被分解成‘var’,'a','=','4',';' 在词法分析时,一个关键字是一个token,一个标识符也是一个token,一个操作符、标点符号也是一个token,它会忽略空格和换行符、注释等。 最后,整个代码被分解装进一个token数组。 token数组示例: [ { type: "Keyword", value: "const" }, { type: "Identifier", value: "num" }, { type: "Punctuator", value: "=" }, { type: "Numeric", value: "10" }, { type: "Punctuator", value: ";" }, ]; 之所以称之为扫描,是因为它会一个一个的读取代码中的字符。

2.解析--语法分析

这个过程会将词法单元流转换成一个由元素相互嵌套的、表示程序的语法结构的树,叫做抽象语法树(AST)。同时会检测语法是否错误,如果有错误,就会抛出语法错误,导致整个js文件终止加载。如果没有错误,就会进入预编译阶段。 我们使用的 Webpack 打包工具中 babel 用的解析器是 Acorn。

在生成树的时候,AST会删除掉一些没有用的字符,比如不完整的括号等。因此AST不是与源码100%匹配的。

3.预编译

js通过语法分析阶段之后,就会进入预编译阶段,函数声明提升和变量声明就发生在这个阶段。

demo示例:

var a = 42;
var b = 5;
function addA(d) {
   return a + d;
}
var c = addA(2) + b;

词法分析之后: 在这里插入图片描述 该过程其实就是将程序中的每一句进行平铺分析。

语法分析之后:

在这里插入图片描述 树上的每一个节点表示源代码中的一种结构,之所以说他是抽象的,是因为他不会表示代码中的每一个细节,比如说,嵌套括号被隐含在树的结构中,并没有以节点的形式呈现。抽象语法树并不依赖于源语言的语法。 在线AST点这里

Q2:AST用处是什么?

  1. babel转码

babel是一个javascript编译器。它分为三个阶段运行代码:解析(parsing),转译(transforming),生成(generation)。 简单来说:生成AST,遍历AST修改代码,重新生成代码。

在这里插入图片描述 2. 自动代码重构工具(JSCodeshift)

当我们想要对项目中比较老旧的代码进行翻新的时候,比如将匿名函数都换成箭头函数,使用简单的查找和替换功能已经无法满足需求了,这个时候就用到了JSCodeshift。 JSCodeshift是如何实现的? JSCodeshift也是通过遍历AST,修改AST中的内容,进而转换为代码来达到目的的(与babel类似)。

在这里插入图片描述 3. prettier格式化代码

prettier是我们平时都会用到的代码格式化工具。它会帮助我们修改代码中的空格、括号和标点符号等。它将代码作为输入,修改后的代码作为输出,那它中间的处理过程做了些什么?

在这里插入图片描述 思路还是一样。首先,将代码生成AST。之后依然是处理AST,最后生成代码。但是,中间过程其实并不像它看起来那么简单。

总结:经过上述举例,我们发现平时我们使用的很多插件都使用了AST,javascript转译、代码压缩、css预处理器、elint、pretiier等。

参考文章:juejin.cn/post/684490…