热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

JavaScriptAST抽象语法树常见节点及结构

文章目录前言Program(程序)Identifier(标识符)Literal(字面量)Vari

文章目录

  • 前言
  • Program(程序)
  • Identifier(标识符)
  • Literal(字面量)
  • VariableDeclarator(变量声明符)
  • Property(属性)
  • Declaration(声明)
    • VariableDeclaration-变量声明
    • FunctionDeclaration-函数声明
  • Statement(语句)
    • BlockStatement-块语句
    • ExpressionStatement-表达式语句
    • IFStatement-如果语句
    • WhileStatement-While循环语句
    • ForStatement-For循环语句
    • ReturnSatement-返回语句
  • Expression(表达式)
    • AssignmentExpression-赋值表达式
    • FunctionExpression-函数表达式
    • BinaryExpression-二元表达式
    • MemberExpression-成员表达式
    • CallExpression-调用表达式
    • ObjectExpression-对象表达式
    • ArrayExpression-数组表达式
    • UpdateExpression-更新运算表达式
    • SequenceExpression-序列表达式
  • 参考文章


前言

最近开始接触AST,用于解决JS代码混淆的问题。

在看@渔哥的文章,虽然目前还是有点云里雾里的。

本文总结了JS抽象语法树中常见节点及结构。

推荐使用下方网站,结合例子对照观察。

工具网站:https://astexplorer.net/



Program(程序)

结构:

{"type": "Program","body": [], // 多个节点"sourceType": "module","range": [] //代码起始位置
}

Identifier(标识符)

可以简单的理解为变量名,函数名,属性名

{"type": "Identifier","name": "", //"range": [] // 代码起始位置
}

例子:

a
_$0x

Literal(字面量)

可以理解为一个具体的值

结构:

{"type": "Literal","value": 1, // 真实值"raw": "1", // 字符串形式的值"range": []
}

例子:

1
'2'
0x10

VariableDeclarator(变量声明符)

属于declarations中的一个元素

var a = 1, b = 2;

其中 a = 1 b = 2属于两个变量声明符

结构:

{"type": "VariableDeclarator","id": Identifier, // 变量名"init": null, // 初始化,如果声明并赋值,此处就有值,只声明未赋值则为null"range": []
}

例子:

var a, b = 2;

Property(属性)

属于properties的元素

键值对

由于 ES5 语法中有 get/set 的存在,所以有一个 kind 属性,用来表示是普通的初始化,或者是 get/set

结构:

{"type": "Property","key": "", // 键"computed": "","value": "", // 值"kind": "init","method": false,"shorthand": false,"range": []
}

Declaration(声明)

VariableDeclaration-变量声明


声明变量

结构:

{'type': "VariableDeclaration",'declarations': [VariableDeclarator, VariableDeclarator...], // `具体的声明, 这是一个列表,因为可以一次性声明多个变量`'kind': "变量修饰符,例如,var、let、const",'range': []// 声明代码的起始位置
}

例子:

var a;
var c, b;

FunctionDeclaration-函数声明


函数的声明

结构:

{'type': 'FunctionDeclaration','id': '', // 可以简单的理解为函数名'params': [], // 参数'body': BlockSatement // 函数的主体内容,多为块语句'generator': false,'expression': false,'async': false,'range': []
}

例子:

function func(a, b) {}

Statement(语句)

BlockStatement-块语句


代码块,简单点理解就是{}包起来的代码

结构:

{"type": "BlockStatement","body": [], // 代码主体"range": []
}

例子:

function a () {}
{}

ExpressionStatement-表达式语句

结构:

{"type": "ExpressionStatement","expression": // 表达式, 例如赋值表达式"range": []
}

IFStatement-如果语句


if 语句

if (a === 1) {}

结构:

{'type': 'IFStatement','test': '', // 判断,if语句()中的内容'consequent': '', // 结果,就是满足这个条件后,后续要执行的代码块'alternate': '', // else 中的内容,如果没有else,则为null'range':
}

举例:

if (a === 1) {console.log(1);
} else {console.log(2);
}

WhileStatement-While循环语句

结构:

{"type": "WhileStatement","test": ,//"body": BlockStatement// 循环体内的代码块"range": []
}

例子:

while (1) {}

ForStatement-For循环语句

结构:

{"type": "ForStatement","init": // 初始化, 多为变量的声明"test": BinaryExpression // 判断"update": UpdateExpression // 更新表达式"range": []
}

例子:

for (var i &#61; 0; i < p.length; i&#43;&#43;) {
}

ReturnSatement-返回语句

结构&#xff1a;

{"type": "RetuenStatement","argument": // 返回的值, 可以是具体的值&#xff0c;也可以是一个表达式"range": []
}

例子&#xff1a;

function func() {return 1;
}

Expression&#xff08;表达式&#xff09;

如果要执行一个表达式&#xff0c;必定由 语句 携带着。


AssignmentExpression-赋值表达式


给变量赋值

结构&#xff1a;

{"type": "AssignmentExpression","operator": "&#61;","left": Identifier, // 操作符左边, 多为Identifier"right": // 操作符右边, 可能为&#xff0c;Identifier&#xff0c;Literal&#xff0c; FucntionExpression"range": [] // 代码起始位置
}

例子&#xff1a;

a &#61; 1;
a &#43;&#61; 1;
a |&#61; 1;
a ^&#61; 2;

FunctionExpression-函数表达式


{"type": "FunctionExpression""id": null"params": [Identifier, ] // 函数的参数"body": BlockStatement// 函数体&#xff0c; 就是大括号里面的代码 "generator": false,"expression": false,"async": false,"range": []
}

BinaryExpression-二元表达式


结构&#xff1a;

{&#39;type&#39;: &#39;BinaryExpression&#39;,&#39;operator&#39;: &#39;&#61;&#61;&#61;&#39; // 二元操作符&#xff0c;比较操作符&#xff0c; <, > , &#61;&#61;&#61;&#xff0c;&#43;&#xff0c;- ...&#39;left&#39;: &#39;&#39; // 操作符的左边&#39;right&#39;: &#39;&#39; // 操作符的右边
}

MemberExpression-成员表达式


简言之&#xff0c;就是访问对象的某个属性&#xff0c;这个属性就是成员

结构&#xff1a;

{&#39;type&#39;: &#39;MemberExpression&#39;,&#39;computed&#39;: true&#xff0c; // 计算, a[&#39;a&#39;]为true&#xff0c; a.a为false&#39;object&#39;: &#39;&#39;, // 对象&#39;property&#39;: &#39;&#39;&#xff0c; // 成员名&#39;range&#39;: // 代码起始位置
}

例子&#xff1a;

a.a
a[&#39;a&#39;]

两者对比

image-20210606110152169

CallExpression-调用表达式


用于函数的调用&#xff0c;

结构&#xff1a;

{&#39;type&#39;: &#39;CallExpression&#39;,&#39;callee&#39;: &#39;&#39;, // 被调用者&#xff0c;可以理解为被调用的方法&#39;arguments&#39;: [], // 传递的参数&#39;range&#39;: []
}

举例&#xff1a;

console.log(1);

此时的callee&#xff0c;就是console.log&#xff0c;则类型为MemberExpression

atob(&#39;a&#39;)

此时的calledd&#xff0c;就是atob&#xff0c;则类型为Identifier

ObjectExpression-对象表达式


结构&#xff1a;

{"type": "ObjectExpression","properties": [Property, Property], // 属性"range": []
}

ArrayExpression-数组表达式

结构&#xff1a;

{"type": "ArrayExpression","elements": [], // 元素"range": []
}

例子&#xff1a;

a &#61; [1, 2]

UpdateExpression-更新运算表达式


update 运算表达式节点&#xff0c;即 &#43;&#43;/--&#xff0c;和一元运算符类似&#xff0c;只是 operator 指向的节点对象类型不同&#xff0c;这里是 update 运算符。

结构&#xff1a;

{"type": "UpdateExpression","operator": "&#43;&#43;", // 或者--"argument": ,"prefix": false, // 运算符&#xff0c;是否在前面&#xff0c;&#43;&#43;i则为true&#xff0c; i&#43;&#43;为false"range": []
}

例子&#xff1a;

i&#43;&#43;
&#43;&#43;i

SequenceExpression-序列表达式

结构&#xff1a;

{"type": "SequenceExpression","expressions": [], // 包含的序列节点"range": []
}

例子&#xff1a;

function func () {var a &#61; 1;return a &#61; 2, 2
}

a &#61; 2, 2就是序列表达式

参考文章

[1] 13 个示例快速入门 JS 抽象语法树


推荐阅读
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • 本文介绍了如何利用JavaScript或jQuery来判断网页中的文本框是否处于焦点状态,以及如何检测鼠标是否悬停在指定的HTML元素上。 ... [详细]
  • 本文详细介绍了 Dockerfile 的编写方法及其在网络配置中的应用,涵盖基础指令、镜像构建与发布流程,并深入探讨了 Docker 的默认网络、容器互联及自定义网络的实现。 ... [详细]
  • 本文详细介绍了Java中org.eclipse.ui.forms.widgets.ExpandableComposite类的addExpansionListener()方法,并提供了多个实际代码示例,帮助开发者更好地理解和使用该方法。这些示例来源于多个知名开源项目,具有很高的参考价值。 ... [详细]
  • 使用 Azure Service Principal 和 Microsoft Graph API 获取 AAD 用户列表
    本文介绍了一段通用代码示例,该代码不仅能够操作 Azure Active Directory (AAD),还可以通过 Azure Service Principal 的授权访问和管理 Azure 订阅资源。Azure 的架构可以分为两个层级:AAD 和 Subscription。 ... [详细]
  • 本文详细记录了在基于Debian的Deepin 20操作系统上安装MySQL 5.7的具体步骤,包括软件包的选择、依赖项的处理及远程访问权限的配置。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • Explore how Matterverse is redefining the metaverse experience, creating immersive and meaningful virtual environments that foster genuine connections and economic opportunities. ... [详细]
  • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
  • 本文详细介绍了如何解决Uploadify插件在Internet Explorer(IE)9和10版本中遇到的点击失效及JQuery运行时错误问题。通过修改相关JavaScript代码,确保上传功能在不同浏览器环境中的一致性和稳定性。 ... [详细]
  • 导航栏样式练习:项目实例解析
    本文详细介绍了如何创建一个具有动态效果的导航栏,包括HTML、CSS和JavaScript代码的实现,并附有详细的说明和效果图。 ... [详细]
  • 本文介绍了如何使用JQuery实现省市二级联动和表单验证。首先,通过change事件监听用户选择的省份,并动态加载对应的城市列表。其次,详细讲解了使用Validation插件进行表单验证的方法,包括内置规则、自定义规则及实时验证功能。 ... [详细]
  • 本文深入探讨 MyBatis 中动态 SQL 的使用方法,包括 if/where、trim 自定义字符串截取规则、choose 分支选择、封装查询和修改条件的 where/set 标签、批量处理的 foreach 标签以及内置参数和 bind 的用法。 ... [详细]
  • 深入解析Spring Cloud Ribbon负载均衡机制
    本文详细介绍了Spring Cloud中的Ribbon组件如何实现服务调用的负载均衡。通过分析其工作原理、源码结构及配置方式,帮助读者理解Ribbon在分布式系统中的重要作用。 ... [详细]
author-avatar
无极圈颜汐
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有