资讯专栏INFORMATION COLUMN

一看就懂的JS抽象语法树

HackerShell / 3331人阅读

摘要:前言是现在几乎每个项目中必备的一个东西,但是其工作原理避不开对的解析在生成的过程,有引擎,早期了项目,了解这个之前我们先来看看这种引擎解析出来是什么东西。

前言

babel是现在几乎每个项目中必备的一个东西,但是其工作原理避不开对js的解析在生成的过程,babel有引擎babylon,早期fork了项目acron,了解这个之前我们先来看看这种引擎解析出来是什么东西。不光是babel还有webpack等都是通过javascript parser将代码转化成抽象语法树,这棵树定义了代码本身,通过操作这颗树,可以精准的定位到赋值语句、声明语句和运算语句

什么是抽象语法树

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

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

我们通过这个网站,他是一个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源码
acron源码
speed comparison
AST explorer
esprima可视化
在线可视化AST

总结

抽象树在前端用的很多很多,现在流行的工具,不管是webpack还是babel都会通过那个三板斧的流程,这里我只是大致介绍一下,过段时间,会出一篇抽象树的语法,有兴趣的也可以把esprima的源码看一下,为什么是esprima呢,因为esprima的资料比较多,而acron比较轻量级。有兴趣的可以关注一下我的[github](),记得点个star,就当是对笔者的支持,谢谢。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/92696.html

相关文章

  • 一看懂的module.exports/exports与module.export/export d

    摘要:命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系。意思是导出的不是一个具体的数值,而是一个对象命令接受一对大括号,里面指定要从其他模块导入的变量名。大括号里面的变量名,必须与被导入模块对外接口的名称相同。 一、module.exports与exports nodeJS采用commonJs规范,当前文件是一个模块(module)私有域,通过exports属性导出,通过re...

    ZoomQuiet 评论0 收藏0
  • 一看懂的例子告诉你用react-redux的正确姿势

    摘要:很多小白在看过很多教程之后仍然在敲代码的时候不清楚应该以什么样的步骤进行,那么这篇文章就一步一步分解整个过程,慢动作回放让大家看的清清楚楚明明白白。另外,中视图部分最好单独出来,放在新建一个文件夹目录下,并被名为引用,把其他逻辑部分放后者。 whay write this: 很多小白在看过很多教程之后仍然在敲代码的时候不清楚应该以什么样的步骤进行,那么这篇文章就一步一步分解整个过程,慢...

    DobbyKim 评论0 收藏0
  • 一看懂的javascript全等于与等于

    Javascript只有六个假值(用在条件if的判断) showImg(https://segmentfault.com/img/bVLiHL?w=424&h=346); 全等于 类型不同,返回false类型相同,则 showImg(https://segmentfault.com/img/bVLiHS?w=476&h=341); 等于 类型相同:同上=== 类型不同:尝试类型转换==【不是真值和...

    Apollo 评论0 收藏0
  • 一看懂的Java线程池分析详解

    摘要:任务性质不同的任务可以用不同规模的线程池分开处理。线程池在运行过程中已完成的任务数量。如等于线程池的最大大小,则表示线程池曾经满了。线程池的线程数量。获取活动的线程数。通过扩展线程池进行监控。框架包括线程池,,,,,,等。 Java线程池 [toc] 什么是线程池 线程池就是有N个子线程共同在运行的线程组合。 举个容易理解的例子:有个线程组合(即线程池,咱可以比喻为一个公司),里面有3...

    Yangder 评论0 收藏0
  • 实现一个简易的webpack

    摘要:首先一段代码转化成的抽象语法树是一个对象,该对象会有一个顶级的属性第二个属性是是一个数组。最终完成整个文件依赖的处理。参考文章抽象语法树一看就懂的抽象语法树源码所有的源码已经上传 背景 随着前端复杂度的不断提升,诞生出很多打包工具,比如最先的grunt,gulp。到后来的webpack和 Parcel。但是目前很多脚手架工具,比如vue-cli已经帮我们集成了一些构建工具的使用。有的时...

    darcrand 评论0 收藏0

发表评论

0条评论

HackerShell

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<