如何将自定义嵌套树结构转换为JS MemberExpression AST结构?
转换实现思路
1. 节点映射规则
- 自定义
form: "site"节点 → 对应非计算属性的MemberExpression:computed: false,property是该节点对应的Identifier节点 - 自定义
form: "nest"节点 → 对应计算属性的MemberExpression:computed: true,property是该节点内部嵌套的表达式(可以是Identifier或者另一个MemberExpression)
2. 核心遍历逻辑
成员表达式是左结合的链式结构,比如a.b[c]实际结构为((a).b)[c],因此转换时需要从最左侧的根标识符开始,依次向右遍历所有属性节点,逐层包裹生成MemberExpression:
- 将自定义树拆解为根节点和按从左到右顺序排列的属性节点列表
- 初始化当前AST节点为根节点对应的Identifier
- 遍历属性节点列表,每一步用当前AST节点作为新MemberExpression的
object,根据当前属性节点的form设置computed值,把属性节点的内容转换为property,生成的新MemberExpression作为下一轮的当前AST节点 - 遍历完成后得到的当前AST节点就是完整的成员表达式
3. 代码实现示例
假设你给出的表达式a.b[c.d][e].f[g[h[i.j]]]对应的自定义树结构如下(为适配逻辑做的标准约定,可根据你实际的自定义树字段调整):
const customTree = { root: 'a', properties: [ { form: 'site', value: 'b' }, { form: 'nest', value: { root: 'c', properties: [{ form: 'site', value: 'd' }] } }, { form: 'nest', value: 'e' }, { form: 'site', value: 'f' }, { form: 'nest', value: { root: 'g', properties: [{ form: 'nest', value: { root: 'h', properties: [{ form: 'nest', value: { root: 'i', properties: [{ form: 'site', value: 'j' }] } }] } }] }} ] }
对应的转换函数实现:
function transformCustomTreeToMemberExpr(customNode) { // 生成根节点对应的标识符 let currentAst = { type: 'Identifier', name: customNode.root } // 逐层遍历属性生成嵌套的MemberExpression for (const prop of customNode.properties) { let propertyAst // 嵌套的自定义树结构递归转换 if (typeof prop.value === 'object' && 'root' in prop.value) { propertyAst = transformCustomTreeToMemberExpr(prop.value) } else { // 普通属性值直接生成标识符 propertyAst = { type: 'Identifier', name: prop.value } } currentAst = { type: 'MemberExpression', object: currentAst, property: propertyAst, computed: prop.form === 'nest' } } return currentAst }
4. 结果校验
将转换后的AST和acorn解析同一表达式得到的AST做结构对比,重点校验两个核心点即可确认正确性:
- 每一层的
computed值是否和自定义节点的form属性完全对应 - MemberExpression的嵌套顺序是否为左结合,最内层的object是最左侧的根标识符,外层依次包裹右侧的属性
内容的提问来源于stack exchange,提问作者Lance Pollard
相关产品推荐
相关产品推荐

