手写babel插件-第二讲

这是手写babel系列的第二讲。这一讲我们来说说抽象语法树(AST)。今天是2024年 大年初一,在这里先祝大家新年快乐,龙年行大运。

AST是干啥的?

它是我们源代码的一种抽象表示。更具体的来说就是使用树状结构去表示代码的语法结构

AST是如何生成的?

它的形成可以分为3个步骤,分别是 词法分析语法分析语义分析

这里有一个问题,大家需要了解这方面的知识吗?我们拿到AST去做一些事情,可以利用AST可视化网站,这很方便的,比如下面这样:

我觉着是一定要了解的。功利性的来讲,如果你在面试过程中遇到了相关的问题,而如果你把AST可视化网站搬过去应付面试官的话,那大概率这个知识点你是不通过,虽然利用AST网站去做源代码转换的事情 这是一个事实。

词法分析

这个过程主要就是读取代码,将代码都拆解成一个一个的最小单元(有人管它叫tokens,也有人管它叫做单词,叫啥不重要,能够知道它是AST的最小组成单元即可)。

语法分析

在词法分析的基础上,根据语言的语法规则,分析程序基本语法结构,并将最小单元组成树状结构。

语义分析

这一步主要是用来检查源代码是否存在语法错误,如果有错误的话就直接抛出来。

如何写一个最简单的babel插件

上面这个作为了解就可以了,不必过多深入。接下来我们来看看如何写一个babel插件。

还是一样,先打开AST可视化网站,然后选中transform选项,如下图:

我们看到,左下方,默认就有一个babel插件。左上方是一段js源代码,右上方是源代码对应的AST。左上方的js源代码 经过 左下方的babel插件处理后生成了右下方的目标代码

那我们接下来就一起探讨一下 这个babel插件是如何编写的。

节点(node)

右上方是实时的AST,它里面的每个对象,都可以被叫做一个节点。

这些节点都有以下类似的结构:

javascript 复制代码
{
  type: "XXXXX",
  name: ...,
  id: {...},
  params: [...],
  left: {...},
  right: {...},
  body: {...}
}

上面的这些属性里,type字段是必须要有的,用来标识当前节点的类型。它是一个枚举,包含 XxDeclaration、XxStatement、XxExpression等等。

插件里的babel参数

javascript 复制代码
export default function (babel) {
  const { types: t } = babel;
  
  return {
    name: "ast-transform", // not required
    visitor: {
      Identifier(path) {
        path.node.name = path.node.name.split('').reverse().join('');
      }
    }
  };
}

首先,我们看到,一个babel插件其实就是一个函数,然后,这个函数需要返回一个对象objobj需要拥有一个访问者vistor属性。这个vistor属性的值也是一个对象b对象b由不同的函数属性构成

babel参数其实指代的是 @babel/core 这个核心模块,里面包含了一些工具方法。比如babel.types对象,这个对象里包含了很多的方法,支持你去创建不同类型的节点。比如:babel.types.stringLiteral方法用于创建一个字符串值。

本篇文章里暂时还用不到,后续文章会有讲到。

vistor访问者

它主要是用来处理节点的增删改查的。所以它是很重要的一个概念。我们知道,节点的类型有很多种,你想要处理哪个,就要把这一类的节点类型写在一个函数里去处理。

以我们这里为例子:

javascript 复制代码
let tips = [];

我们要写一个插件,用来将上述代码的 let 改为 const,那我们要怎么写呢?

首先,将我们的代码放到 AST可视化网站上,随后,我们应该有如下思路:

  • let这个关键字,对于AST来说,它也是一个节点。
  • 既然let都是一个节点了,那const也应该是一个节点。
  • 这个需求其实也就是替换节点。
  • 替换节点的代码位置应该在哪里呢?刚才我们讲过,vistor就是干这个事的。
  • 如何写呢?我们刚才也说过,你要把同一个类型的节点处理写在一个函数里。
  • 那我怎么知道let属于哪个类型的节点?AST可视化网站不就派上用场了嘛。你把上面的代码放到这个可视化网站里看一下不就知道啦。
  • 经过查看得知,let 的节点类型 是VariableDeclaration

于是,我们就可以写出下面的babel插件:

javascript 复制代码
export default function (babel) {
  const { types: t } = babel;
  
  return {
    name: "ast-transform", // not required
    visitor: {
      VariableDeclaration(path){
      	path.node.kind = 'const';
      }
    }
  };
}

最后发现,我们如约的完成了这个需求。

最后

好啦,本期babel分享到这里就结束啦,希望我的分享能够对你有帮助,我们下期再见啦~~

相关推荐
拾光拾趣录4 分钟前
CSS 深入解析:提升网页样式技巧与常见问题解决方案
前端·css
莫空00005 分钟前
深入理解JavaScript属性描述符:从数据属性到存取器属性
前端·面试
guojl6 分钟前
深度剖析Kafka读写机制
前端
FogLetter6 分钟前
图片懒加载:让网页飞起来的魔法技巧 ✨
前端·javascript·css
Mxuan7 分钟前
vscode webview 插件开发(精装篇)
前端
Mxuan8 分钟前
vscode webview 插件开发(交付篇)
前端
Mxuan9 分钟前
vscode 插件与 electron 应用跳转网页进行登录的实践
前端
拾光拾趣录10 分钟前
JavaScript 加载对浏览器渲染的影响
前端·javascript·浏览器
Codebee10 分钟前
OneCode图表配置速查手册
大数据·前端·数据可视化
然我10 分钟前
React 开发通关指南:用 HTML 的思维写 JS🚀🚀
前端·react.js·html