1.enter方式进行遍历(不写默认是enter方式)
假设我们需要处理的代码如下:
var a = 'a' + 'b' + 'c' + d + 'e' + 'f';
想要对上面的 代码 进行字符串的合并操作,遍历 BinaryExpression类型,代码如下:
const visitor = { "BinaryExpression"(path) { console.log(path.toString()) const {confident, value} = path.evaluate(); confident && path.replaceWith(types.valueToNode(value)); }, } traverse(ast, visitor);
我们知道,当没有指明以什么方式进行遍历时,会默认以enter方式进行遍历,上面的插件运行结果如下:
最后处理后的代码变成了这样:
var a = "abc" + d + 'e' + 'f';
我们在插件的第一行打印出了当前所遍历path的源代码,可以看到①②③④是按顺序进行遍历的,是逐渐向底部进行遍历,直到无法遍历。可以将上面的代码略微的调整下:
var a = 'a' + 'b' + 'c' + 'd' + 'e' + 'f';
再次运行上面的插件,打印的结果如下:
这一次为什么只遍历了一次呢?那是因为第一次遍历后,结果变成了一个 StringLiteral 类型的表达式,
var a = 'abcdef';
已不再是 BinaryExpression 类型,因此不会再次遍历。甚至可以将path的left节点和right节点分别打印出来看看效果:
const visitor = { "BinaryExpression"(path) { console.log(path.get('left').toString()); console.log(path.get('right').toString()); const {confident, value} = path.evaluate(); confident && path.replaceWith(types.valueToNode(value)); }, } traverse(ast, visitor);
2.exit方式进行遍历
当指明以exit方式进行遍历时,插件及部分代码如下:
const visitor = { "BinaryExpression": { exit: function (path) { console.log(path.toString()) const {confident, value} = path.evaluate(); confident && path.replaceWith(types.valueToNode(value)); } }, } traverse(ast, visitor);
很明显和上面enter方式遍历的顺序不一样,大致分析如下:
-
left : 'a'; right:'b' ---> 结果合并为'ab'。
-
left : 'ab'; right:'c' ---> 结果合并为'abc'。
-
left : 'abc'; right:d ---> 结果没法合并,但他们已经成为一个整体 'acb' + d
-
left : 'abc'+d; right:'e' ---> 结果没法合并,但他们已经成为一个整体 'acb' + d + 'e';
-
left : 'abc'+d + 'e'; right:'f' ---> 结果没法合并,但他们已经成为一个整体 'acb' + d + 'e' + 'f';
-
不再是BinaryExpression 类型,停止遍历。
上面的left和right表示BinaryExpression 类型的左右子节点。
我画了个示意图,大家可以看看:
标签:遍历,AST,visitor,区别,right,exit,BinaryExpression,path,left From: https://www.cnblogs.com/yoyo1216/p/17854823.html