本文探讨如何编写Babel插件,为JavaScript默认添加不可变数据。文章深入讲解了抽象语法树(AST)的概念及其在Babel插件中的作用,并通过逐步的代码示例,演示了如何构建一个将普通对象和数组字面量转换为Mori库中持久化数据结构的Babel插件。
核心要点:
语言概述:
我们的目标是设计一个插件,允许我们使用常规的对象和数组字面量,这些字面量将使用Mori库转换为持久化数据结构。
我们希望编写这样的代码:
var foo = { a: 1 }; var baz = foo.a = 2; foo.a === 1; baz.a === 2;
并将其转换为如下代码:
var foo = mori.hashMap('a', 1); var baz = mori.assoc(foo, 'a', 2); mori.get(foo, 'a') === 1; mori.get(baz, 'a') === 2;
让我们开始使用MoriScript!
Babel概述:
如果我们深入研究Babel,就会发现三个重要的工具处理了大部分流程。
Babylon是解析器,它知道如何将JavaScript代码字符串转换为称为抽象语法树(AST)的计算机友好表示。
babel-traverse
模块允许您探索、分析并可能修改AST。
最后,babel-generator
模块用于将转换后的AST转换回常规代码。
什么是AST?
在继续本教程之前,理解AST的目的至关重要。让我们深入了解它们是什么以及为什么我们需要它们。
JavaScript程序通常由一系列字符组成,每个字符对我们人类的大脑都有一定的视觉意义。这对我们来说非常有效,因为它允许我们使用匹配的字符([]
、{}
、()
)、字符对(''
、""
)和缩进,使我们的程序更容易解释。
然而,这对计算机来说并没有多大帮助。对它们来说,每个字符都只是内存中的一个数值,它们无法使用这些字符来提出诸如“此声明中有多少个变量?”之类的高级问题。相反,我们需要妥协,找到一种方法将我们的代码转换成我们可以编程和计算机可以理解的东西。
请看以下代码:
var foo = { a: 1 }; var baz = foo.a = 2; foo.a === 1; baz.a === 2;
当我们为此程序生成AST时,最终会得到一个如下所示的结构:
所有AST都以树根处的Program节点开始,其中包含程序中所有顶级语句。在本例中,我们只有两个:
尽管它们是由简单的构建块组成的,但AST的大小意味着它们通常非常复杂,特别是对于非平凡的程序。与其自己尝试弄清楚AST,我们可以使用astexplorer.net,它允许我们在左边输入JavaScript,然后在右边输出可探索的AST表示。在继续的过程中,我们将专门使用此工具来理解和试验代码。
为了与Babel保持一致,请确保选择“babylon6”作为解析器。
在编写Babel插件时,我们的工作是获取AST,然后插入/移动/替换/删除一些节点以创建一个新的AST,该AST可用于生成代码。
设置:
在开始之前,请确保已安装node和npm。然后为项目创建一个文件夹,创建一个package.json
文件并安装以下开发依赖项。
var foo = mori.hashMap('a', 1); var baz = mori.assoc(foo, 'a', 2); mori.get(foo, 'a') === 1; mori.get(baz, 'a') === 2;
然后,我们将为我们的插件创建一个文件,并在其中导出一个默认函数。
var a = 3; a + 5
此函数公开了访问者模式的接口,我们稍后将回到它。
最后,我们将创建一个运行器,以便在进行过程中测试我们的插件。
mkdir moriscript && cd moriscript npm init -y npm install --save-dev babel-core
我们可以使用MoriScript示例文件的名称来调用此脚本,以检查它是否生成了我们期望的JavaScript。例如,node run.js example.ms
。
(以下内容继续介绍数组、对象和赋值的处理,以及最终的结论和常见问题解答,与原文保持一致,但语言和结构进行了调整,使其更流畅自然。由于篇幅限制,此处省略了原文剩余部分的伪原创内容。)
以上是通过构建自己的Babel插件来了解AST的详细内容。更多信息请关注PHP中文网其他相关文章!