栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > Web开发 > JavaScript

13 个例子快速了解JS抽象语法树

JavaScript 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

13 个例子快速了解JS抽象语法树

Javascript 代码的解析(Parse )步骤分为两个阶段:**词法分析(Lexical Analysis) **和 语法分析(Syntactic Analysis)。这个步骤接收代码并输出 抽象语法树,亦称 AST。

随着 Babel 的生态越来越完善,我们通常会使用 Babel 来帮助我们分析代码的解析过程。Babel 使用一个基于 ESTree 并修改过的 AST,它的内核说明文档可以在 [这里](https://github. com/babel/babel/blob/master/doc/ast/spec. md) 找到。

在分析 Javascript 的 AST 过程中,借助于工具 AST Explorer  能帮助我们对 AST 节点有一个更好的感性认识。

为了帮助大家更好的结合实例分析,了解核心的 Babylon AST node types 组成,这里列举了 13 个常用例子,并分别列出了对应的 AST 节点及详细的 node types 解析。

以下所有的代码的 AST 全部基于 Babylon7

变量声明代码
let a  = 'hello'
AST

image

VariableDeclaration

变量声明,kind 属性表示是什么类型的声明,因为 ES6 引入了 const/let。
declarations 表示声明的多个描述,因为我们可以这样:let a = 1, b = 2;。

interface VariableDeclaration <: Declaration {    type: "VariableDeclaration";    declarations: [ VariableDeclarator ];    kind: "var";
}
VariableDeclarator

变量声明的描述,id 表示变量名称节点,init 表示初始值的表达式,可以为 null。

interface VariableDeclarator <: Node {    type: "VariableDeclarator";    id: Pattern;    init: expression | null;
}
Identifier

标识符,我觉得应该是这么叫的,就是我们写 JS 时自定义的名称,如变量名,函数名,属性名,都归为标识符。相应的接口是这样的:

interface Identifier <: expression, Pattern {    type: "Identifier";    name: string;
}

一个标识符可能是一个表达式,或者是解构的模式(ES6 中的解构语法)。我们等会会看到 expression 和 Pattern 相关的内容的。

Literal

字面量,这里不是指 [] 或者 {} 这些,而是本身语义就代表了一个值的字面量,如 1,“hello”, true 这些,还有正则表达式(有一个扩展的 Node 来表示正则表达式),如 /d?/。我们看一下文档的定义:

interface Literal <: expression {    type: "Literal";    value: string | boolean | null | number | RegExp;
}

value 这里即对应了字面量的值,我们可以看出字面量值的类型,字符串,布尔,数值,null 和正则。

二元运算表达式代码
let a = 3+4
AST

image

Binaryexpression

二元运算表达式节点,left 和 right 表示运算符左右的两个表达式,operator 表示一个二元运算符。

interface Binaryexpression <: expression {    type: "Binaryexpression";    operator: BinaryOperator;    left: expression;    right: expression;
}
BinaryOperator

二元运算符,所有值如下:

enum BinaryOperator {    "==" | "!=" | "===" | "!=="
         | "<" | "<=" | ">" | ">="
         | "<<" | ">>" | ">>>"
         | "+" | "-" | "*" | "/" | "%"
         | "|" | "^" | "&" | "in"
         | "instanceof"}
赋值表达式代码

这个例子会稍微复杂一点,涉及到的 Node 类型比较多。

    this.state = {date: new Date()};
AST

image

expressionStatement

表达式语句节点,a = a + 1 或者 a++ 里边会有一个 expression 属性指向一个表达式节点对象(后边会提及表达式)。

interface expressionStatement <: Statement {    type: "expressionStatement";    expression: expression;
}
Assignmentexpression

赋值表达式节点,operator 属性表示一个赋值运算符,left 和 right 是赋值运算符左右的表达式。

interface Assignmentexpression <: expression {    type: "Assignmentexpression";    operator: AssignmentOperator;    left: Pattern | expression;    right: expression;
}
AssignmentOperator

赋值运算符,所有值如下:(常用的并不多)

enum AssignmentOperator {    "=" | "+=" | "-=" | "*=" | "/=" | "%="
        | "<<=" | ">>=" | ">>>="
        | "|=" | "^=" | "&="}
Memberexpression

成员表达式节点,即表示引用对象成员的语句,object 是引用对象的表达式节点,property 是表示属性名称,computed 如果为 false,是表示 . 来引用成员,property 应该为一个 Identifier 节点,如果 computed 属性为 true,则是 [] 来进行引用,即 property 是一个 expression 节点,名称是表达式的结果值。

interface Memberexpression <: expression, Pattern {    type: "Memberexpression";    object: expression;    property: expression;    computed: boolean;
}
Thisexpression

表示 this。

interface Thisexpression <: expression {    type: "Thisexpression";
}
Objectexpression

对象表达式节点,property 属性是一个数组,表示对象的每一个键值对,每一个元素都是一个属性节点。

interface Objectexpression <: expression {    type: "Objectexpression";    properties: [ Property ];
}
Property

对象表达式中的属性节点。key 表示键,value 表示值,由于 ES5 语法中有 get/set 的存在,所以有一个 kind 属性,用来表示是普通的初始化,或者是 get/set。

interface Property <: Node {    type: "Property";    key: Literal | Identifier;    value: expression;    kind: "init" | "get" | "set";
}
Newexpression

new 表达式。

interface Newexpression <: Callexpression {    type: "Newexpression";
}
函数调用表达式代码
    console.log(`Hello ${name}`)
AST

image

Callexpression

函数调用表达式,即表示了 func(1, 2) 这一类型的语句。callee 属性是一个表达式节点,表示函数,arguments 是一个数组,元素是表达式节点,表示函数参数列表。

interface Callexpression <: expression {    type: "Callexpression";    callee: expression;    arguments: [ expression ];
}
TemplateLiteral
interface TemplateLiteral <: expression {  type: "TemplateLiteral";  quasis: [ TemplateElement ];  expressions: [ expression ];
}
TemplateElement
interface TemplateElement <: Node {  type: "TemplateElement";  tail: boolean;  value: {
    cooked: string | null;    raw: string;
  };
}
箭头函数代码
i => i++
AST

image

ArrowFunctionexpression

箭头函数表达式。

interface ArrowFunctionexpression <: Function, expression {  type: "ArrowFunctionexpression";  body: BlockStatement | expression;  expression: boolean;
}
Updateexpression

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

interface Updateexpression <: expression {    type: "Updateexpression";    operator: UpdateOperator;    argument: expression;    prefix: boolean;
}
UpdateOperator

update 运算符,值为 ++ 或 --,配合 update 表达式节点的 prefix 属性来表示前后。

enum UpdateOperator {    "++" | "--"}
函数声明代码
function Hello(name = 'Lily'){
    
}
AST

image

FunctionDeclaration

函数声明,和之前提到的 Function 不同的是,id 不能为 null。

interface FunctionDeclaration <: Function, Declaration {    type: "FunctionDeclaration";    id: Identifier;
}
AssignmentPattern
interface AssignmentPattern <: Pattern {  type: "AssignmentPattern";  left: Pattern;  right: expression;
}
BlockStatement

块语句节点,举个例子:if (...) { // 这里是块语句的内容 },块里边可以包含多个其他的语句,所以有一个 body 属性,是一个数组,表示了块里边的多个语句。

interface BlockStatement <: Statement {    type: "BlockStatement";    body: [ Statement ];
}
类声明代码
class Clock extends Component{
    render(){
    }
}
AST

[站外图片上传中...(image-597960-1532005358414)]

Classes
interface Class <: Node {  id: Identifier | null;  superClass: expression | null;  body: ClassBody;  decorators: [ Decorator ];
}
ClassBody
interface ClassBody <: Node {  type: "ClassBody";  body: [ ClassMethod | ClassPrivateMethod | ClassProperty | ClassPrivateProperty ];
}
ClassMethod
interface ClassMethod <: Function {  type: "ClassMethod";  key: expression;  kind: "constructor" | "method" | "get" | "set";  computed: boolean;  static: boolean;  decorators: [ Decorator ];
}
if 语句代码
if(a === 0){
}
AST

image

IfStatement

if 语句节点,很常见,会带有三个属性,test 属性表示 if (...) 括号中的表达式。

consequent 属性是表示条件为 true 时的执行语句,通常会是一个块语句。

alternate 属性则是用来表示 else 后跟随的语句节点,通常也会是块语句,但也可以又是一个 if 语句节点,即类似这样的结构:
if (a) { //... } else if (b) { // ... }。
alternate 当然也可以为 null。

interface IfStatement <: Statement {    type: "IfStatement";    test: expression;    consequent: Statement;    alternate: Statement | null;
}
switch 语句代码
switch(num){  case 0:
    x = 'Sunday'
    break;  default:
    x = 'Weekday'}
AST

image

SwitchStatement

switch 语句节点,有两个属性,discriminant 属性表示 switch 语句后紧随的表达式,通常会是一个变量,cases 属性是一个 case 节点的数组,用来表示各个 case 语句。

interface SwitchStatement <: Statement {    type: "SwitchStatement";    discriminant: expression;    cases: [ SwitchCase ];
}
SwitchCase

switch 的 case 节点。test 属性代表这个 case 的判断表达式,consequent 则是这个 case 的执行语句。

当 test 属性是 null 时,则是表示 default 这个 case 节点。

interface SwitchCase <: Node {    type: "SwitchCase";    test: expression | null;    consequent: [ Statement ];
}
for 语句代码
for (var i = 0; i < 9; i++) {
}
AST

image

ForStatement

for 循环语句节点,属性 init/test/update 分别表示了 for 语句括号中的三个表达式,初始化值,循环判断条件,每次循环执行的变量更新语句(init 可以是变量声明或者表达式)。这三个属性都可以为 null,即 for(;;){}。
body 属性用以表示要循环执行的语句。

interface ForStatement <: Statement {    type: "ForStatement";    init: VariableDeclaration | expression | null;    test: expression | null;    update: expression | null;    body: Statement;
}
模块引入代码
import React from 'react'
AST

[站外图片上传中...(image-7f97a0-1532005358414)]

importDeclaration

模块声明。

interface importDeclaration <: ModuleDeclaration {  type: "importDeclaration";  specifiers: [ importSpecifier | importDefaultSpecifier | importNamespaceSpecifier ];  source: Literal;
}
importDefaultSpecifier
interface importDefaultSpecifier <: ModuleSpecifier {  type: "importDefaultSpecifier";
}
模块导出代码
export default Clock
AST

image

ExportDefaultDeclaration
interface OptFunctionDeclaration <: FunctionDeclaration {  id: Identifier | null;
}interface OptClasDeclaration <: ClassDeclaration {  id: Identifier | null;
}interface ExportDefaultDeclaration <: ModuleDeclaration {  type: "ExportDefaultDeclaration";  declaration: OptFunctionDeclaration | OptClassDeclaration | expression;
}
JSX render 方法代码:
  render() {    return (      
        Hello, world!
        It is {this.state.date.toLocaleTimeString()}.
      
    );
  }
AST

image

参考
  • babel-handbook

  • babylon spec.md

  • estree

  • 使用 Acorn 来解析 Javascript



作者:Pines_Cheng
链接:https://www.jianshu.com/p/1ae5cbcd97b6


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/246406.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号