更多博客文章,欢迎 Star Github/Blog
Javascript 代码的解析(Parse )步骤分为两个阶段:词法分析(Lexical Analysis) 和 语法分析(Syntactic Analysis)。这个步骤接收代码并输出 抽象语法树,亦称 AST。node
随着 Babel 的生态愈来愈完善,咱们一般会使用 Babel 来帮助咱们分析代码的解析过程。Babel 使用一个基于 ESTree 并修改过的 AST,它的内核说明文档能够在 这里. com/babel/babel/blob/master/doc/ast/spec. md) 找到。react
在分析 Javascript 的 AST 过程当中,借助于工具 AST Explorer 能帮助咱们对 AST 节点有一个更好的感性认识。git
为了帮助你们更好的结合实例分析,了解核心的 Babylon AST node types 组成,这里列举了 13 个经常使用例子,并分别列出了对应的 AST 节点及详细的 node types 解析。github
如下全部的代码的 AST 所有基于 Babylon7
let a = 'hello'
变量声明,kind
属性表示是什么类型的声明,由于 ES6 引入了 const/let
。declarations
表示声明的多个描述,由于咱们能够这样:let a = 1, b = 2;
。正则表达式
interface VariableDeclaration <: Declaration { type: "VariableDeclaration"; declarations: [ VariableDeclarator ]; kind: "var"; }
变量声明的描述,id
表示变量名称节点,init
表示初始值的表达式,能够为 null
。express
interface VariableDeclarator <: Node { type: "VariableDeclarator"; id: Pattern; init: Expression | null; }
标识符,我以为应该是这么叫的,就是咱们写 JS 时自定义的名称,如变量名,函数名,属性名,都归为标识符。相应的接口是这样的:数组
interface Identifier <: Expression, Pattern { type: "Identifier"; name: string; }
一个标识符多是一个表达式,或者是解构的模式(ES6 中的解构语法)。咱们等会会看到 Expression
和 Pattern
相关的内容的。babel
字面量,这里不是指 []
或者 {}
这些,而是自己语义就表明了一个值的字面量,如 1
,“hello”
, true
这些,还有正则表达式(有一个扩展的 Node
来表示正则表达式),如 /\d?/
。咱们看一下文档的定义:函数
interface Literal <: Expression { type: "Literal"; value: string | boolean | null | number | RegExp; }
value
这里即对应了字面量的值,咱们能够看出字面量值的类型,字符串,布尔,数值,null
和正则。工具
let a = 3+4
二元运算表达式节点,left
和 right
表示运算符左右的两个表达式,operator
表示一个二元运算符。
interface BinaryExpression <: Expression { type: "BinaryExpression"; operator: BinaryOperator; left: Expression; right: Expression; }
二元运算符,全部值以下:
enum BinaryOperator { "==" | "!=" | "===" | "!==" | "<" | "<=" | ">" | ">=" | "<<" | ">>" | ">>>" | "+" | "-" | "*" | "/" | "%" | "|" | "^" | "&" | "in" | "instanceof" }
这个例子会稍微复杂一点,涉及到的 Node 类型比较多。
this.state = {date: new Date()};
表达式语句节点,a = a + 1
或者 a++
里边会有一个 expression
属性指向一个表达式节点对象(后边会说起表达式)。
interface ExpressionStatement <: Statement { type: "ExpressionStatement"; expression: Expression; }
赋值表达式节点,operator
属性表示一个赋值运算符,left
和 right
是赋值运算符左右的表达式。
interface AssignmentExpression <: Expression { type: "AssignmentExpression"; operator: AssignmentOperator; left: Pattern | Expression; right: Expression; }
赋值运算符,全部值以下:(经常使用的并很少)
enum AssignmentOperator { "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "<<=" | ">>=" | ">>>=" | "|=" | "^=" | "&=" }
成员表达式节点,即表示引用对象成员的语句,object
是引用对象的表达式节点,property
是表示属性名称,computed
若是为 false
,是表示 .
来引用成员,property
应该为一个 Identifier
节点,若是 computed
属性为 true
,则是 []
来进行引用,即 property
是一个 Expression
节点,名称是表达式的结果值。
interface MemberExpression <: Expression, Pattern { type: "MemberExpression"; object: Expression; property: Expression; computed: boolean; }
表示 this
。
interface ThisExpression <: Expression { type: "ThisExpression"; }
对象表达式节点,property
属性是一个数组,表示对象的每个键值对,每个元素都是一个属性节点。
interface ObjectExpression <: Expression { type: "ObjectExpression"; properties: [ Property ]; }
对象表达式中的属性节点。key
表示键,value
表示值,因为 ES5 语法中有 get/set
的存在,因此有一个 kind
属性,用来表示是普通的初始化,或者是 get/set
。
interface Property <: Node { type: "Property"; key: Literal | Identifier; value: Expression; kind: "init" | "get" | "set"; }
new
表达式。
interface NewExpression <: CallExpression { type: "NewExpression"; }
console.log(`Hello ${name}`)
函数调用表达式,即表示了 func(1, 2)
这一类型的语句。callee
属性是一个表达式节点,表示函数,arguments
是一个数组,元素是表达式节点,表示函数参数列表。
interface CallExpression <: Expression { type: "CallExpression"; callee: Expression; arguments: [ Expression ]; }
interface TemplateLiteral <: Expression { type: "TemplateLiteral"; quasis: [ TemplateElement ]; expressions: [ Expression ]; }
interface TemplateElement <: Node { type: "TemplateElement"; tail: boolean; value: { cooked: string | null; raw: string; }; }
i => i++
箭头函数表达式。
interface ArrowFunctionExpression <: Function, Expression { type: "ArrowFunctionExpression"; body: BlockStatement | Expression; expression: boolean; }
update 运算表达式节点,即 ++/--
,和一元运算符相似,只是 operator
指向的节点对象类型不一样,这里是 update 运算符。
interface UpdateExpression <: Expression { type: "UpdateExpression"; operator: UpdateOperator; argument: Expression; prefix: boolean; }
update 运算符,值为 ++
或 --
,配合 update 表达式节点的 prefix
属性来表示先后。
enum UpdateOperator { "++" | "--" }
function Hello(name = 'Lily'){ }
函数声明,和以前提到的 Function 不一样的是,id
不能为 null
。
interface FunctionDeclaration <: Function, Declaration { type: "FunctionDeclaration"; id: Identifier; }
interface AssignmentPattern <: Pattern { type: "AssignmentPattern"; left: Pattern; right: Expression; }
块语句节点,举个例子:if (...) { // 这里是块语句的内容 }
,块里边能够包含多个其余的语句,因此有一个 body
属性,是一个数组,表示了块里边的多个语句。
interface BlockStatement <: Statement { type: "BlockStatement"; body: [ Statement ]; }
class Clock extends Component{ render(){ } }
interface Class <: Node { id: Identifier | null; superClass: Expression | null; body: ClassBody; decorators: [ Decorator ]; }
interface ClassBody <: Node { type: "ClassBody"; body: [ ClassMethod | ClassPrivateMethod | ClassProperty | ClassPrivateProperty ]; }
interface ClassMethod <: Function { type: "ClassMethod"; key: Expression; kind: "constructor" | "method" | "get" | "set"; computed: boolean; static: boolean; decorators: [ Decorator ]; }
if(a === 0){ }
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(num){ case 0: x = 'Sunday' break; default: x = 'Weekday' }
switch
语句节点,有两个属性,discriminant
属性表示 switch
语句后紧随的表达式,一般会是一个变量,cases
属性是一个 case
节点的数组,用来表示各个 case
语句。
interface SwitchStatement <: Statement { type: "SwitchStatement"; discriminant: Expression; cases: [ SwitchCase ]; }
switch
的 case
节点。test
属性表明这个 case
的判断表达式,consequent
则是这个 case
的执行语句。
当 test
属性是 null
时,则是表示 default
这个 case
节点。
interface SwitchCase <: Node { type: "SwitchCase"; test: Expression | null; consequent: [ Statement ]; }
for (var i = 0; i < 9; i++) { }
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'
模块声明。
interface ImportDeclaration <: ModuleDeclaration { type: "ImportDeclaration"; specifiers: [ ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier ]; source: Literal; }
interface ImportDefaultSpecifier <: ModuleSpecifier { type: "ImportDefaultSpecifier"; }
export default Clock
interface OptFunctionDeclaration <: FunctionDeclaration { id: Identifier | null; } interface OptClasDeclaration <: ClassDeclaration { id: Identifier | null; } interface ExportDefaultDeclaration <: ModuleDeclaration { type: "ExportDefaultDeclaration"; declaration: OptFunctionDeclaration | OptClassDeclaration | Expression; }
render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.state.date.toLocaleTimeString()}.</h2> </div> ); }