本篇文章给大家谈谈 JavaScript 抽象语法树. 有一定的参考价值, 有需要的朋友可以参考一下, 希望对大家有所帮助.
前言
babel 是现在几乎每个项目中必备的一个东西, 但是其工作原理避不开对 JS 的解析在生成的过程, babel 有引擎 babylon, 早期 fork 了项目 acron, 了解这个之前我们先来看看这种引擎解析出来是什么东西. 不光是 babel 还有 webpack 等都是通过 JavaScript parser 将代码转化成抽象语法树, 这棵树定义了代码本身, 通过操作这颗树, 可以精准的定位到赋值语句, 声明语句和运算语句
什么是抽象语法树
我们可以来看一个简单的例子:
- var a = 1;
- var b = a + 1;
我们通过这个网站 http://esprima.org/demo/parse.html# , 他是一个 esprima 引擎的网站, 十分好用. 画成流程图如下:
而他的 JSON 对象格式是这样的:
- {
- "type": "Program",
- "body": [
- {
- "type": "VariableDeclaration",
- "declarations": [
- {
- "type": "VariableDeclarator",
- "id": {
- "type": "Identifier",
- "name": "a"
- },
- "init": {
- "type": "Literal",
- "value": 1,
- "raw": "1"
- }
- }
- ],
- "kind": "var"
- },
- {
- "type": "VariableDeclaration",
- "declarations": [
- {
- "type": "VariableDeclarator",
- "id": {
- "type": "Identifier",
- "name": "b"
- },
- "init": {
- "type": "BinaryExpression",
- "operator": "+",
- "left": {
- "type": "Identifier",
- "name": "a"
- },
- "right": {
- "type": "Literal",
- "value": 1,
- "raw": "1"
- }
- }
- }
- ],
- "kind": "var"
- }
- ],
- "sourceType": "script"
- }
众多的引擎
Chrome 有 v8,firefix 有 spidermonkey. 还有一些常用的引擎有:
- esprima
- acron
- Traceur
- UglifyJS2
- shift
下面是一些引擎的速度对比, 以及用不同的框架, 引擎们的加载速度:
我个人认为, 封装的越完美的, 其实解析的时间更长, 引擎之间也是 acron 这个速度比较优秀, babel 引擎前身就是 fork 这个项目的.
AST 的三板斧
通过 esprima 生成 AST
通过 estraverse 遍历和更新 AST
通过 escodegen 将 AST 重新生成源码
我们可以来做一个简单的例子:
1. 先新建一个 test 的工程目录
2. 在 test 工程下安装 esprima,estraverse,escodegen 的 NPM 模块
NPM i esprima estraverse escodegen --save
3. 在目录下面新建一个 test.JS 文件, 载入以下代码:
- const esprima = require('esprima');
- let code = 'const a = 1';
- const ast = esprima.parseScript(code);
- console.log(ast);
你将会看到输出结果:
- Script {
- type: 'Program',
- body:
- [ VariableDeclaration {
- type: 'VariableDeclaration',
- declarations: [Array],
- kind: 'const' } ],
- sourceType: 'script' }
4. 再在 test 文件中, 载入以下代码:
- const estraverse = require('estraverse');
- estraverse.traverse(ast, {
- enter: function (node) {
- node.kind = "var";
- }
- });
- console.log(ast);
输出的结果:
- Script {
- type: 'Program',
- body:
- [ VariableDeclaration {
- type: 'VariableDeclaration',
- declarations: [Array],
- kind: 'var' } ],
- sourceType: 'script' }
5. 最后在 test 文件中, 加入以下代码:
- const escodegen = require("escodegen");
- const transformCode = escodegen.generate(ast)
- console.log(transformCode);
输出的结果:
var a = 1;
通过这三板斧: 我们将 const a = 1 转化成了 var a = 1
有没有 babel 的感觉 0.0
推荐网站
esprima 源码 https://github.com/jquery/esprima
acron 源码 https://github.com/ternjs/acorn
- speed comparison http://esprima.org/test/compare.html
- AST explorer https://astexplorer.net/
esprima 可视化 http://esprima.org/demo/parse.html#
在线可视化 AST http://resources.jointjs.com/demos
总结
抽象树在前端用的很多很多, 现在流行的工具, 不管是 webpack 还是 babel 都会通过那个三板斧的流程, 这里我只是大致介绍一下, 过段时间, 会出一篇抽象树的语法, 有兴趣的也可以把 esprima 的源码看一下, 为什么是 esprima 呢, 因为 esprima 的资料比较多, 而 acron 比较轻量级.
本文转载自: https://segmentfault.com/a/1190000012943992
更多 Web 前端开发 https://www.html.cn/ 知识, 请查阅 HTML 中文网 !!
来源: http://www.css88.com/web/javascript/17136.html