面试官: 你了解过Babel吗?写过Babel插件吗? 答: 没有。卒

网站建设4年前发布
20 0 0

202303061206087959364016f246a34e959719af62af3374ed9c402,面试大厂,其中有那么一个问题:,了解过抽象语法树,又称AST,有学习过,也写过一个基于AST的乞丐版模板引擎,先是词法解析token,然后生产抽象语法树,然后更改抽象语法树,当然这是插件做的事情,最后根据新的AST生成代码。,没有,只是看过相关文档,啊,这,我试试!,遂卒....,开玩笑的,既然提到了,又没回答上来什么,哎哟我这暴脾气,一想到今晚就睡不着,连夜把它撸了。,那么我们来从零写个插件吧。,写一个预计算简单表达式的插件,Before:,After:,以上的例子可能大家不会经常遇到,因为傻x才会这么写,但是有可能你会这么写,在写代码之前,你需要明白Babel它的原理,简单点说:Babel解析成AST,然后插件更改AST,最后由Babel输出代码。,那么Babel的插件模块需要你暴露一个function,function内返回visitor。,visitor是对各类型的AST节点做处理的地方,那么我们怎么知道Babel生成了的AST有哪些节点呢?,很简单,你可以把Babel转换的结果打印出来,或者这里有传送门: AST explorer:https://astexplorer.net/,2023030610281999792b440a61958f22970879d3e9321b4c53ef236,这里我们看到 const result = 1 + 2中的1 + 1是一个BinaryExpression节点,那么在visitor中,我们就处理这个节点,插件写好了,我们运行下插件试试,与预期一致,那么转换 const result = 1 + 2 + 3 + 4 + 5;呢?,结果是: const result = 3 + 3 + 4 + 5;,这就奇怪了,为什么只计算了1 + 2之后,就没有继续往下运算了?,我们看一下这个表达式的AST树,20230306103344c37fbb30292b58fc9c77433186fb280efdd00b700,你会发现Babel解析成表达式里面再嵌套表达式。,而我们的判断条件并不符合所有的,只符合1 + 2,那么我们得改一改,第一次计算1 + 2之后,我们会得到这样的表达式,其中 3 + 3又符合了我们的条件, 我们通过向上递归的方式遍历父级节点 又转换成这样:,到这里,我们就得出了结果 const result = 15;,那么其他运算呢:,到这里,已经向你大概的讲解了,如何编写一个Babel插件,再也不怕面试官问我答不出什么了哈...,你以为这就完了吗?,并没有,如果转换这样呢: const result = 0.1 + 0.2;,预期肯定是0.3, 但是实际上,Javascript有浮点计算误差,得出的结果是0.30000000000000004,那是不是这个插件就没卵用?,这就需要你去矫正浮点运算误差了,可以使用Big.js; 比如: result = node.left.value + node.right.value; 改成 result = +new Big(node.left.value).plus(node.right.value);你以为完了吗? 这个插件还可以做很多,有旁友指出:,parentPath那一块可以换个实现方法。第一个binaryExpression真正被计算之后是会被替换成numericLiteral的。由于每个node都会被visit两次,所以在exit访问时,对于父节点而言两个子节点又同时是numericLiteral了,再次执行即可。,也就是说,只要在enter和exit节点的时候,都执行一下上面替换节点的代码就行,无须手动遍历父节点去计算并替换~,真是个不错的方法呢!

© 版权声明

相关文章