资讯专栏INFORMATION COLUMN

简单玩一下AST(JavaScript)

FrozenMap / 784人阅读

摘要:简单来说就是一个对于代码的一个编译过程,进行了词法分析与语法分析的过程。转换对于进行变换一系列的操作,接受得到并通过对其进行遍历,在此过程中进行添加更新及移除等操作。而模块则是将三者结合使得对外提供的做了一个简化。

直奔主题

对于js,AST能干什么?

babel将es6转es5

mpvue、taro等将js转为小程序

定制插件删除注释、console等

ps: 本文只探讨AST的概念以及使用,编译原理的其他知识不做太多描述

工具库

@babel/core

用来解析AST以及将AST生成代码

@babel/types

构建新的AST节点

前置知识 - 编译原理概述

毫无疑问js是一个解释型语言,有疑问可以参考这篇文章
所以这里只简单描述一下babel的编译过程(大雾),有兴趣了解编译型语言详细编译过程的可以看这本 《编译原理》

和编译器类似,babel 的转译过程也分为三个阶段,这三步具体是:

解析 Parse
将代码解析生成抽象语法树( 即AST ),也就是计算机理解我们代码的方式(扩展:一般来说每个 js 引擎都有自己的 AST,比如熟知的 v8,chrome 浏览器会把 js 源码转换为抽象语法树,再进一步转换为字节码或机器代码),而 babel 则是通过babylon 实现的 。简单来说就是一个对于 JS 代码的一个编译过程,进行了词法分析与语法分析的过程。

转换 Transform
对于 AST 进行变换一系列的操作,babel 接受得到 AST 并通过 babel-traverse 对其进行遍历,在此过程中进行添加、更新及移除等操作。

生成 Generate
将变换后的 AST 再转换为 JS 代码, 使用到的模块是 babel-generator

babel-core 模块则是将三者结合使得对外提供的API做了一个简化。

生成AST

demo.js是我随便copy来的一段代码

isLeapYear()

function isLeapYear(year) {
    const cond1 = year % 4 == 0;  //条件1:年份必须要能被4整除
    const cond2 = year % 100 != 0;  //条件2:年份不能是整百数
    const cond3 = year % 400 ==0;  //条件3:年份是400的倍数
    const cond = cond1 && cond2 || cond3;

    console.log(cond)

    if(cond) {
        alert(year + "是闰年");
        return true;
    } else {
        alert(year + "不是闰年");
        return false;
    }
}

现在我要把它转成AST,这里使用@babel/core来解析,它提供了一个parse方法来将代码转化为AST。

parse.ts就是我的解析工具

import * as fs from "fs"
import * as path from "path"

import { parse} from "@babel/core"

const js_path = path.resolve(__dirname, "../demo.js")
let code = fs.readFileSync(js_path, {
    encoding: "utf-8"
})

const js_ast = parse(code)
console.log(js_ast)

可以看到AST结果如下:

结果太长就不一一解析了,只说type属性,就表示了这一行代码做了什么,VariableDeclaration就表示这是一句声明语句, CallExpression则代表这是一个调用函数的语句

将AST转回代码

@babel/core提供了一个transform方法,输入代码和修改代码的规则,输出修改过的AST,它看起来是这样的:

const ArrowPlugins = {
    visitor: {
        VariableDeclaration(path: NodePath) {
            // ...
        },
        CallExpression(path: NodePath) {
            // ...
        }
    }
}

const d = transform(code, {
    plugins: [
        ArrowPlugins
    ]
})

当命中对应的type时就会走进相应的回调函数,接下来写个小

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

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

相关文章

  • 平庸前端码农之蜕变 — AST

    摘要:为什么要谈抽象语法树如果你查看目前任何主流的项目中的,会发现前些年的不计其数的插件诞生。什么是抽象语法树估计很多同学会和图中的喵一样,看完这段官方的定义一脸懵逼。它读取我们的代码,然后把它们按照预定的规则合并成一个个的标识。 前言 首先,先说明下该文章是译文,原文出自《AST for JavaScript developers》。很少花时间特地翻译一篇文章,咬文嚼字是件很累的事情,实在...

    dreamans 评论0 收藏0
  • 造轮子系列(三): 一个简单快速的html虚拟语法树(AST)解析器

    摘要:前言虚拟语法树是解释器编译器进行语法分析的基础也是众多前端编译工具的基础工具比如等对于由于前端轮子众多人力过于充足早已经被人们玩腻了光是语法分析器就有等等若干种并且也有了的社区标准这篇文章主要介绍如何去写一个解析器但是并不是通过分析而是通过 前言 虚拟语法树(Abstract Syntax Tree, AST)是解释器/编译器进行语法分析的基础, 也是众多前端编译工具的基础工具, 比如...

    Genng 评论0 收藏0
  • 造轮子系列(三): 一个简单快速的html虚拟语法树(AST)解析器

    摘要:前言虚拟语法树是解释器编译器进行语法分析的基础也是众多前端编译工具的基础工具比如等对于由于前端轮子众多人力过于充足早已经被人们玩腻了光是语法分析器就有等等若干种并且也有了的社区标准这篇文章主要介绍如何去写一个解析器但是并不是通过分析而是通过 前言 虚拟语法树(Abstract Syntax Tree, AST)是解释器/编译器进行语法分析的基础, 也是众多前端编译工具的基础工具, 比如...

    SQC 评论0 收藏0
  • JS学习系列 01 - 编译原理和作用域

    摘要:的抽象语法树中可能如下图所示代码生成将转换为可执行代码的过程被称为代码生成。如果是,编译器会忽略该声明,继续进行编译,否则它会要求在当前作用域的集合中声明一个新的变量,并命名为。 在学习 javascript 的过程中,我们第一步最应该了解和掌握的就是作用域,与之相关还有程序是怎么编译的,变量是怎么查找的,js 引擎是什么,引擎和作用域的关系又是什么,这些是 javascript 这门...

    jkyin 评论0 收藏0

发表评论

0条评论

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