亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定

13 個例子快速了解JS抽象語法樹

標簽:
JavaScript

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 全部基于

AST

webp

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 中的解构语法)。我们等会会看到 ExpressionPattern 相关的内容的。

Literal

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

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

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

二元运算表达式

代码

let a = 3+4

AST

webp

image

BinaryExpression

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

interface BinaryExpression <: Expression {    type: "BinaryExpression";    operator: BinaryOperator;    left: Expression;    right: Expression;
}

BinaryOperator

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

enum BinaryOperator {    "==" | "!=" | "===" | "!=="
         | "<" | "<=" | ">" | ">="
         | "<<" | ">>" | ">>>"
         | "+" | "-" | "*" | "/" | "%"
         | "|" | "^" | "&" | "in"
         | "instanceof"}

赋值表达式

代码

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

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

AST

webp

image

ExpressionStatement

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

interface ExpressionStatement <: Statement {    type: "ExpressionStatement";    expression: Expression;
}

AssignmentExpression

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

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

webp

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

webp

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

webp

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

webp

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

webp

image

SwitchStatement

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

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

SwitchCase

switchcase 节点。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

webp

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

webp

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 (      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }

AST

webp

image

参考



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


點擊查看更多內容
TA 點贊

若覺得本文不錯,就分享一下吧!

評論

作者其他優質文章

正在加載中
  • 推薦
  • 評論
  • 收藏
  • 共同學習,寫下你的評論
感謝您的支持,我會繼續努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦
今天注冊有機會得

100積分直接送

付費專欄免費學

大額優惠券免費領

立即參與 放棄機會
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號

舉報

0/150
提交
取消