更多博客文章,歡迎 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> ); }