摘要:操作通常配合来完成。因为是个数组,因此,我们可以直接使用数组操作自我毁灭方法极为简单,找到要删除的,执行就结束了。如上述代码,我们要删除属性,代码如下到目前为止,的我们都介绍完了,下面一篇文章以转小程序为例,我们来实战一波。
通过前两篇文章的介绍,大家已经了解了Create和Retrieve,我们接着介绍Update和 Remove操作。Update操作通常配合Create来完成。我们这篇文章主要介绍几个常用的NodePath`API:replace、insert、remove`。具体也可以看babel-handbook中的Manipulation章节。
replaceWith 使用新的节点进行替换 将加法运算替换成乘法const code = `const c = a + b` const ast = babylon.parse(code) traverse(ast, { BinaryExpression(path) { // 注意这里要有判断,否则会无限进入`BinaryExpression` // https://stackoverflow.com/questions/37539432/babel-maximum-call-stack-size-exceeded-while-using-path-replacewith if (path.node.operator === "+") { path.replaceWith(t.binaryExpression("*", path.node.left, path.node.right)) } } }) console.log(generate(ast, {}, code).code) // const c = a * b;将this.count替换为this.data.count
转换前后的AST展示如下图:
我们需要做的是,找到符合this.count的ThisExpression,然后把它替换为this.data
const code = `this.count` const ast = babylon.parse(code) traverse(ast, { MemberExpression(path) { if ( t.isThisExpression(path.node.object) && t.isIdentifier(path.node.property, { name: "count" }) ) { path .get("object") // 获取`ThisExpresssion` .replaceWith( t.memberExpression(t.thisExpression(), t.identifier("data")) ) } } }) console.log(generate(ast, {}, code).code) // this.data.count;replaceWithSourceString 直接使用代码替换
上个例子中将this.count替换为this.data.count的部分,通过t.memberExpression可以构造node。更简单的操作可以直接使用replaceWithSourceString,个人觉得这个API很好用。
path.get("object").replaceWithSourceString("this.data")插入操作
插入是树操作的一种常见操作。子节点是个Array,前、中、后各种位置都可以插入新节点。下面来介绍下pushContainer、unshiftContainer、insertBefore、insertAfter操作。
这里以给obj对象新增一个属性myprop: "hello my property"为例:
const code = ` const obj = { count: 0, message: "hello world" } ` const ast = babylon.parse(code) const property = t.objectProperty( t.identifier("myprop"), t.stringLiteral("hello my property") )pushContainer 父节点的操作
父节点为子节点Array插入一个node
traverse(ast, { ObjectExpression(path) { path.pushContainer("properties", property) } })insertAfter 兄弟节点的操作
insertAfter也可以完成上述操作,需要找到message属性,然后在后面插入node就搞定啦
traverse(ast, { ObjectProperty(path) { if ( t.isIdentifier(path.node.key, { name: "message" }) ) { path.insertAfter(property) } } })
unshiftContainer和insertBefore与上面两个相对应,这里不再举例了,大家可以自己试一试。
因为properties是个数组,因此,我们可以直接使用数组操作
traverse(ast, { ObjectExpression(path) { // path.pushContainer("properties", property) path.node.properties.push(property) } })Remove 自我毁灭
Remove方法极为简单,找到要删除的NodePath,执行Remove就结束了。如上述代码,我们要删除message属性,代码如下:
traverse(ast, { ObjectProperty(path) { if ( t.isIdentifier(path.node.key, { name: "message" }) ) { path.remove() } } })
到目前为止,AST的CURD我们都介绍完了,下面一篇文章以vue转小程序为例,我们来实战一波。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/107868.html
摘要:针对语法树节点的查询操作通常伴随着和这两种方法见下一篇文章。注意上述代码打印出的和中的并不完全一致。如函数,在中的为,但其实际的为。这个大家一定要注意哦,因为在我们后面的实际代码中也有用到。 在上一篇文章中,我们介绍了AST的Create。在这篇文章中,我们接着来介绍AST的Retrieve。 针对语法树节点的查询(Retrieve)操作通常伴随着Update和Remove(这两...
摘要:生成属性这一步,我们要先提取原函数中的的对象。所以这里我们还是主要使用来访问节点获取第一级的,也就是函数体将合并的写法用生成生成生成插入到原函数下方删除原函数程序输出将中的属性提升一级这里遍历中的属性没有再采用,因为这里结构是固定的。 经过之前的三篇文章介绍,AST的CRUD都已经完成。下面主要通过vue转小程序过程中需要用到的部分关键技术来实战。 下面的例子的核心代码依然是最简单...
摘要:思路可以实现时间复杂度的和,但是要求也是,只用是不可以的。但是在里面查找的时间复杂度依然是,可以想到用来记录对应的,这样查找的时间也是常数。用可以保持顺序,但是的时间复杂度是。 380. Insert Delete GetRandom O(1) Design a data structure that supports all following operations in aver...
吃豆人和削苹果这两个游戏想必大家都知道吧,本文运用Python里的Pygame控制模块编写出一个融合吃豆人+切水果的新手游:玩命吃苹果,有兴趣的话可以认识一下 引言 哈哈哈!木木子今天浮现——早已来给大家看了不少具体内容啦~ 涉及到的人工智能、新手、网络爬虫、数据统计分析(这一块的通常但是审批)手机游戏... PS: 吃豆人我写过了哈 Python+Pygame实战之吃豆豆游戏的实...
摘要:首先要做到是,能想到的数据结构只有两三种,一个是,一个是,是,还有一个,是。不太可能,因为长度要而且不可变,题目也没说长度固定。可以做到和都是。因为还有函数,要可以,所以还需要一个数据结构来记录顺序,自然想到。 LRU Cache 题目链接:https://leetcode.com/problems... 这个题要求O(1)的复杂度。首先要做到get(key)是O(1),能想到的数据结...
阅读 1759·2021-11-11 16:55
阅读 2545·2021-08-27 13:11
阅读 3622·2019-08-30 15:53
阅读 2301·2019-08-30 15:44
阅读 1378·2019-08-30 11:20
阅读 1036·2019-08-30 10:55
阅读 943·2019-08-29 18:40
阅读 3029·2019-08-29 16:13