一看就懂的JS抽象语法树

关注“重度前端”

助力前端深度学习

━━━━━


前言

babel是现在几乎每个项目中必备的一个东西,在我们的开发中频繁被使用。了解其工作原理势必让我们对他的使用更加的顺畅和清晰。本文不会太过深入的介绍实现原理,只是有个初步的了解即可。对实现机制有兴趣的同学可以深入的研究。

babel有引擎babylon,早期fork了项目acron,了解这个之前我们先来看看这种引擎解析出来是什么东西。不光是babel还有webpack等都是通过javascript parser将代码转化成抽象语法树,这棵树定义了代码本身,通过操作这颗树,可以精准的定位到赋值语句、声明语句和运算语句。

什么是抽象语法树

我们可以来看一个简单的例子:

 
  

var a = 1;
var b = a + 1;


我们通过这个网站,他是一个esprima引擎的网站,十分好用.画成流程图如下:

640?wx_fmt=png


而他的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

下面是一些引擎的速度对比,以及用不同的框架,引擎们的加载速度:

640?wx_fmt=png


我个人认为,封装的越完美的,其实解析的时间更长,引擎之间也是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, {
    enterfunction (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也是这样实现的呢?其实所有的涉及到代码转换的都是这个原理啦。只是实现的方式不同。


推荐网站以及工具

esprima源码
acron源码
speed comparison
AST explorer
esprima可视化
在线可视化AST


总结

抽象树在前端用的很多很多,现在流行的工具,不管是webpack还是babel都会通过那个三板斧的流程,实际的处理会非常的复杂,这里我只是大致介绍一下。我们可以将这个技术用到实际的工作,从工作中发现痛点,实现自己的js编译工具。有兴趣的也可以把esprima的源码看一下,为什么是esprima呢,因为esprima的资料比较多,而acron比较轻量级。


原文地址:https://segmentfault.com/a/1190000012943992



【点个赞或者分享下,我就干的更带劲儿】

640?wx_fmt=png

 重度前端--助力深度学习

为web前端同行提供有价值、有深度的技术文章

官网:http://bigerfe.com【建设】

640?wx_fmt=jpeg

长按二维码关注我


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值