xvno / blog

个人博客, 不定期发布技术笔记和个人随笔.
0 stars 0 forks source link

JavaScript: AST #93

Open xvno opened 4 years ago

xvno commented 4 years ago

Refs

  1. acorn: 解析内核, 在线工具 AST Explorer
  2. recast: node.js 环境下可以直接用npm安装 recast
xvno commented 4 years ago

What

Abstract Syntax Tree; parser 对源代码执行的 parsing 的结果, 可以认为是一个JSON的树形结构.

xvno commented 4 years ago

1. JavaScript 的 AST 结构

入口

  1. type: Program
  2. souceType: module
  3. body: [] // 代码在此

对于每一样代码, 都会解析到 body 中

  1. 变量声明 & 变量赋值: VariableDeclaration & AssignmentExpression (Number, String, Boolean, null, undefined, Symbol, Object, Array, Function, Date)
  2. 条件语句: { if: IfStatement, 三元操作: ConditionalExpression }
  3. for循环: {for: ForStatement: {init, test, update, body}, for-in: ForInStatement: {left, right, body}, for-of: ForOfStatement}
  4. while循环, do-while循环: WhileStatement, DoWhileStatement
  5. switch: SwitchStatement, SwitchCase, BreakStatement
  6. 函数:声明/表达式和调用; CallExpression, ArrayExpression, ObjectExpression, Literal

Tips

  1. 变量声明 VariableDeclaration
  2. 函数声明 FunctionDeclaration
  3. 块声明 BlockStatement
  4. ForStatement, ForInStatement, ForOfStatement
  5. WhileStatement, DoWhileStatement
  6. SwitchStatement / BreakStatement
  7. ReturnStatement
  8. 普通语句 ExpressionStatement
    • 赋值语句 AssignmentExpression
    • 一元操作 UpdateExpression
    • 二元操作 BinaryExpression
    • 三元操作 ConditionalExpression
    • 数组表达式 ArrayExpression
    • 对象表达式 ObjectExpression
    • 箭头函数 ArrowFunctionExpression
    • 函数调用 CallExpression
    • new表达式 NewExpression
    • 函数表达式 FunctionExpression
xvno commented 4 years ago

1.1 变量声明 & 变量赋值

  1. VariableDeclaration
  2. AssignmentExpression
  3. AssignmentPattern (es6, 默认参数值)
  4. 各种类型数据的赋值
xvno commented 4 years ago
1.1.1 变量声明
// const e = 3;
{
    "type": "VariableDeclaration",
    "start": 0,
    "end": 12,
    "declarations": [
        {
            "type": "VariableDeclarator",
            "start": 6,
            "end": 11,
            "id": {
                "type": "Identifier",
                "start": 6,
                "end": 7,
                "name": "e"
            },
            "init": {
                "type": "Literal",
                "start": 10,
                "end": 11,
                "value": 3,
                "raw": "3"
            }
        }
    ],
    "kind": "const"
}

// let a = 1, b = 2;
{
    "type": "VariableDeclaration",
    "start": 1,
    "end": 20,
    "declarations": [
        {
            "type": "VariableDeclarator",
            "start": 5,
            "end": 10,
            "id": {
                "type": "Identifier",
                "start": 5,
                "end": 6,
                "name": "a"
            },
            "init": {
                "type": "Literal",
                "start": 9,
                "end": 10,
                "value": 1,
                "raw": "1"
            }
        },
        {
            "type": "VariableDeclarator",
            "start": 12,
            "end": 19,
            "id": {
                "type": "Identifier",
                "start": 12,
                "end": 13,
                "name": "b"
            },
            "init": {
                "type": "BinaryExpression",
                "start": 16,
                "end": 19,
                "left": {
                    "type": "Literal",
                    "start": 16,
                    "end": 17,
                    "value": 2,
                    "raw": "2"
                },
                "operator": "^",
                "right": {
                    "type": "Literal",
                    "start": 18,
                    "end": 19,
                    "value": 2,
                    "raw": "2"
                }
            }
        }
    ],
    "kind": "let"
}

// let c = d = 0;
{
    "type": "VariableDeclaration",
    "start": 21,
    "end": 35,
    "declarations": [
        {
            "type": "VariableDeclarator",
            "start": 25,
            "end": 34,
            "id": {
                "type": "Identifier",
                "start": 25,
                "end": 26,
                "name": "c"
            },
            "init": {
                "type": "AssignmentExpression",
                "start": 29,
                "end": 34,
                "operator": "=",
                "left": {
                    "type": "Identifier",
                    "start": 29,
                    "end": 30,
                    "name": "d"
                },
                "right": {
                    "type": "Literal",
                    "start": 33,
                    "end": 34,
                    "value": 0,
                    "raw": "0"
                }
            }
        }
    ],
    "kind": "let"
}
xvno commented 4 years ago
1.1.2 变量赋值
// let a;
{
    "type": "VariableDeclaration",
    "start": 0,
    "end": 6,
    "declarations": [
        {
            "type": "VariableDeclarator",
            "start": 4,
            "end": 5,
            "id": {
                "type": "Identifier",
                "start": 4,
                "end": 5,
                "name": "a"
            },
            "init": null
        }
    ],
    "kind": "let"
}
// a = 1
{
    "type": "ExpressionStatement",
    "start": 8,
    "end": 14,
    "expression": {
        "type": "AssignmentExpression",
        "start": 8,
        "end": 13,
        "operator": "=",
        "left": {
            "type": "Identifier",
            "start": 8,
            "end": 9,
            "name": "a"
        },
        "right": {
            "type": "Literal",
            "start": 12,
            "end": 13,
            "value": 1,
            "raw": "1"
        }
    }
}

// a = 2^3; // 注意 BinaryExpression
{
    "type": "ExpressionStatement",
    "start": 15,
    "end": 23,
    "expression": {
        "type": "AssignmentExpression",
        "start": 15,
        "end": 22,
        "operator": "=",
        "left": {
            "type": "Identifier",
            "start": 15,
            "end": 16,
            "name": "a"
        },
        "right": {
            "type": "BinaryExpression",
            "start": 19,
            "end": 22,
            "left": {
                "type": "Literal",
                "start": 19,
                "end": 20,
                "value": 2,
                "raw": "2"
            },
            "operator": "^",
            "right": {
                "type": "Literal",
                "start": 21,
                "end": 22,
                "value": 3,
                "raw": "3"
            }
        }
    }
}

// function(limit=5){} // 选自limit=5, 其中没有operator

{
    "type": "AssignmentPattern",
    "start": 27,
    "end": 34,
    "left": {
        "type": "Identifier",
        "start": 27,
        "end": 32,
        "name": "limit"
    },
    "right": {
        "type": "Literal",
        "start": 33,
        "end": 34,
        "value": 5,
        "raw": "5"
    }
}
xvno commented 4 years ago
各类变量
// 变量赋值
num = 1
str = 'string'
boo = false
obj = {
  name: 'object'
}
arr = [a, b]
fun = function(){}
nil = null
und = undefined
dat = new Date()
reg = /^reg$/ig

// 属性赋值

obj.num = 3
{
    "type": "ExpressionStatement",
    "start": 8,
    "end": 15,
    "expression": {
        "type": "AssignmentExpression",
        "start": 8,
        "end": 15,
        "operator": "=",
        "left": {
            "type": "Identifier",
            "start": 8,
            "end": 11,
            "name": "num"
        },
        "right": {
            "type": "Literal",
            "start": 14,
            "end": 15,
            "value": 1,
            "raw": "1"
        }
    }
},
{
    "type": "ExpressionStatement",
    "start": 16,
    "end": 30,
    "expression": {
        "type": "AssignmentExpression",
        "start": 16,
        "end": 30,
        "operator": "=",
        "left": {
            "type": "Identifier",
            "start": 16,
            "end": 19,
            "name": "str"
        },
        "right": {
            "type": "Literal",
            "start": 22,
            "end": 30,
            "value": "string",
            "raw": "'string'"
        }
    }
},
{
    "type": "ExpressionStatement",
    "start": 31,
    "end": 42,
    "expression": {
        "type": "AssignmentExpression",
        "start": 31,
        "end": 42,
        "operator": "=",
        "left": {
            "type": "Identifier",
            "start": 31,
            "end": 34,
            "name": "boo"
        },
        "right": {
            "type": "Literal",
            "start": 37,
            "end": 42,
            "value": false,
            "raw": "false"
        }
    }
},
{
    "type": "ExpressionStatement",
    "start": 43,
    "end": 69,
    "expression": {
        "type": "AssignmentExpression",
        "start": 43,
        "end": 69,
        "operator": "=",
        "left": {
            "type": "Identifier",
            "start": 43,
            "end": 46,
            "name": "obj"
        },
        "right": {
            "type": "ObjectExpression",
            "start": 49,
            "end": 69,
            "properties": [
                {
                    "type": "Property",
                    "start": 53,
                    "end": 67,
                    "method": false,
                    "shorthand": false,
                    "computed": false,
                    "key": {
                        "type": "Identifier",
                        "start": 53,
                        "end": 57,
                        "name": "name"
                    },
                    "value": {
                        "type": "Literal",
                        "start": 59,
                        "end": 67,
                        "value": "object",
                        "raw": "'object'"
                    },
                    "kind": "init"
                }
            ]
        }
    }
},
{
    "type": "ExpressionStatement",
    "start": 70,
    "end": 82,
    "expression": {
        "type": "AssignmentExpression",
        "start": 70,
        "end": 82,
        "operator": "=",
        "left": {
            "type": "Identifier",
            "start": 70,
            "end": 73,
            "name": "arr"
        },
        "right": {
            "type": "ArrayExpression",
            "start": 76,
            "end": 82,
            "elements": [
                {
                    "type": "Identifier",
                    "start": 77,
                    "end": 78,
                    "name": "a"
                },
                {
                    "type": "Identifier",
                    "start": 80,
                    "end": 81,
                    "name": "b"
                }
            ]
        }
    }
},
{
    "type": "ExpressionStatement",
    "start": 83,
    "end": 101,
    "expression": {
        "type": "AssignmentExpression",
        "start": 83,
        "end": 101,
        "operator": "=",
        "left": {
            "type": "Identifier",
            "start": 83,
            "end": 86,
            "name": "fun"
        },
        "right": {
            "type": "FunctionExpression",
            "start": 89,
            "end": 101,
            "id": null,
            "expression": false,
            "generator": false,
            "async": false,
            "params": [],
            "body": {
                "type": "BlockStatement",
                "start": 99,
                "end": 101,
                "body": []
            }
        }
    }
},
{
    "type": "ExpressionStatement",
    "start": 102,
    "end": 112,
    "expression": {
        "type": "AssignmentExpression",
        "start": 102,
        "end": 112,
        "operator": "=",
        "left": {
            "type": "Identifier",
            "start": 102,
            "end": 105,
            "name": "nil"
        },
        "right": {
            "type": "Literal",
            "start": 108,
            "end": 112,
            "value": null,
            "raw": "null"
        }
    }
},
{
    "type": "ExpressionStatement",
    "start": 113,
    "end": 128,
    "expression": {
        "type": "AssignmentExpression",
        "start": 113,
        "end": 128,
        "operator": "=",
        "left": {
            "type": "Identifier",
            "start": 113,
            "end": 116,
            "name": "und"
        },
        "right": {
            "type": "Identifier",
            "start": 119,
            "end": 128,
            "name": "undefined"
        }
    }
},
{
    "type": "ExpressionStatement",
    "start": 129,
    "end": 145,
    "expression": {
        "type": "AssignmentExpression",
        "start": 129,
        "end": 145,
        "operator": "=",
        "left": {
            "type": "Identifier",
            "start": 129,
            "end": 132,
            "name": "dat"
        },
        "right": {
            "type": "NewExpression",
            "start": 135,
            "end": 145,
            "callee": {
                "type": "Identifier",
                "start": 139,
                "end": 143,
                "name": "Date"
            },
            "arguments": []
        }
    }
},
{
    "type": "ExpressionStatement",
    "start": 146,
    "end": 161,
    "expression": {
        "type": "AssignmentExpression",
        "start": 146,
        "end": 161,
        "operator": "=",
        "left": {
            "type": "Identifier",
            "start": 146,
            "end": 149,
            "name": "reg"
        },
        "right": {
            "type": "Literal",
            "start": 152,
            "end": 161,
            "value": {},
            "raw": "/^reg$/ig",
            "regex": {
                "pattern": "^reg$",
                "flags": "ig"
            }
        }
    }
},
{
    "type": "ExpressionStatement",
    "start": 174,
    "end": 185,
    "expression": {
        "type": "AssignmentExpression",
        "start": 174,
        "end": 185,
        "operator": "=",
        "left": {
            "type": "MemberExpression",
            "start": 174,
            "end": 181,
            "object": {
                "type": "Identifier",
                "start": 174,
                "end": 177,
                "name": "obj"
            },
            "property": {
                "type": "Identifier",
                "start": 178,
                "end": 181,
                "name": "num"
            },
            "computed": false
        },
        "right": {
            "type": "Literal",
            "start": 184,
            "end": 185,
            "value": 3,
            "raw": "3"
        }
    }
}
xvno commented 4 years ago

1.2. 条件语句: IfStatement, ConditionalExpression(三元操作符)

  1. IfStatement
  2. ConditionalExpression
xvno commented 4 years ago
1.2.1 IfStatement

注意: else if, alternate->IfStatement else{if}, alternate->BlockStatement->IfStatement

if-elseIf(if-else)

if (a > -1) {
    log('Positive');
} else {
    if (a > -2) {
        log('Not too bad');
    } else {
        log('Awful');
    }
}
{
    "type": "IfStatement",
    "start": 0,
    "end": 132,
    "test": {
        "type": "BinaryExpression",
        "start": 4,
        "end": 10,
        "left": {
            "type": "Identifier",
            "start": 4,
            "end": 5,
            "name": "a"
        },
        "operator": ">",
        "right": {
            "type": "UnaryExpression",
            "start": 8,
            "end": 10,
            "operator": "-",
            "prefix": true,
            "argument": {
                "type": "Literal",
                "start": 9,
                "end": 10,
                "value": 1,
                "raw": "1"
            }
        }
    },
    "consequent": {
        "type": "BlockStatement",
        "start": 12,
        "end": 36,
        "body": [
            {
                "type": "ExpressionStatement",
                "start": 18,
                "end": 34,
                "expression": {
                    "type": "CallExpression",
                    "start": 18,
                    "end": 33,
                    "callee": {
                        "type": "Identifier",
                        "start": 18,
                        "end": 21,
                        "name": "log"
                    },
                    "arguments": [
                        {
                            "type": "Literal",
                            "start": 22,
                            "end": 32,
                            "value": "Positive",
                            "raw": "'Positive'"
                        }
                    ]
                }
            }
        ]
    },
    "alternate": {
        "type": "BlockStatement",
        "start": 42,
        "end": 132,
        "body": [
            {
                "type": "IfStatement",
                "start": 48,
                "end": 130,
                "test": {
                    "type": "BinaryExpression",
                    "start": 52,
                    "end": 58,
                    "left": {
                        "type": "Identifier",
                        "start": 52,
                        "end": 53,
                        "name": "a"
                    },
                    "operator": ">",
                    "right": {
                        "type": "UnaryExpression",
                        "start": 56,
                        "end": 58,
                        "operator": "-",
                        "prefix": true,
                        "argument": {
                            "type": "Literal",
                            "start": 57,
                            "end": 58,
                            "value": 2,
                            "raw": "2"
                        }
                    }
                },
                "consequent": {
                    "type": "BlockStatement",
                    "start": 60,
                    "end": 95,
                    "body": [
                        {
                            "type": "ExpressionStatement",
                            "start": 70,
                            "end": 89,
                            "expression": {
                                "type": "CallExpression",
                                "start": 70,
                                "end": 88,
                                "callee": {
                                    "type": "Identifier",
                                    "start": 70,
                                    "end": 73,
                                    "name": "log"
                                },
                                "arguments": [
                                    {
                                        "type": "Literal",
                                        "start": 74,
                                        "end": 87,
                                        "value": "Not too bad",
                                        "raw": "'Not too bad'"
                                    }
                                ]
                            }
                        }
                    ]
                },
                "alternate": {
                    "type": "BlockStatement",
                    "start": 101,
                    "end": 130,
                    "body": [
                        {
                            "type": "ExpressionStatement",
                            "start": 111,
                            "end": 124,
                            "expression": {
                                "type": "CallExpression",
                                "start": 111,
                                "end": 123,
                                "callee": {
                                    "type": "Identifier",
                                    "start": 111,
                                    "end": 114,
                                    "name": "log"
                                },
                                "arguments": [
                                    {
                                        "type": "Literal",
                                        "start": 115,
                                        "end": 122,
                                        "value": "Awful",
                                        "raw": "'Awful'"
                                    }
                                ]
                            }
                        }
                    ]
                }
            }
        ]
    }
}

if-elseIf-else

if (a > -1) {
    log('Positive');
} else if (a > -2) {
    log('Not too bad');
} else {
    log('Awful');
}
{
    "type": "IfStatement",
    "start": 0,
    "end": 108,
    "test": {
        "type": "BinaryExpression",
        "start": 4,
        "end": 10,
        "left": {
            "type": "Identifier",
            "start": 4,
            "end": 5,
            "name": "a"
        },
        "operator": ">",
        "right": {
            "type": "UnaryExpression",
            "start": 8,
            "end": 10,
            "operator": "-",
            "prefix": true,
            "argument": {
                "type": "Literal",
                "start": 9,
                "end": 10,
                "value": 1,
                "raw": "1"
            }
        }
    },
    "consequent": {
        "type": "BlockStatement",
        "start": 12,
        "end": 36,
        "body": [
            {
                "type": "ExpressionStatement",
                "start": 18,
                "end": 34,
                "expression": {
                    "type": "CallExpression",
                    "start": 18,
                    "end": 33,
                    "callee": {
                        "type": "Identifier",
                        "start": 18,
                        "end": 21,
                        "name": "log"
                    },
                    "arguments": [
                        {
                            "type": "Literal",
                            "start": 22,
                            "end": 32,
                            "value": "Positive",
                            "raw": "'Positive'"
                        }
                    ]
                }
            }
        ]
    },
    "alternate": {
        "type": "IfStatement",
        "start": 42,
        "end": 108,
        "test": {
            "type": "BinaryExpression",
            "start": 46,
            "end": 52,
            "left": {
                "type": "Identifier",
                "start": 46,
                "end": 47,
                "name": "a"
            },
            "operator": ">",
            "right": {
                "type": "UnaryExpression",
                "start": 50,
                "end": 52,
                "operator": "-",
                "prefix": true,
                "argument": {
                    "type": "Literal",
                    "start": 51,
                    "end": 52,
                    "value": 2,
                    "raw": "2"
                }
            }
        },
        "consequent": {
            "type": "BlockStatement",
            "start": 54,
            "end": 81,
            "body": [
                {
                    "type": "ExpressionStatement",
                    "start": 60,
                    "end": 79,
                    "expression": {
                        "type": "CallExpression",
                        "start": 60,
                        "end": 78,
                        "callee": {
                            "type": "Identifier",
                            "start": 60,
                            "end": 63,
                            "name": "log"
                        },
                        "arguments": [
                            {
                                "type": "Literal",
                                "start": 64,
                                "end": 77,
                                "value": "Not too bad",
                                "raw": "'Not too bad'"
                            }
                        ]
                    }
                }
            ]
        },
        "alternate": {
            "type": "BlockStatement",
            "start": 87,
            "end": 108,
            "body": [
                {
                    "type": "ExpressionStatement",
                    "start": 93,
                    "end": 106,
                    "expression": {
                        "type": "CallExpression",
                        "start": 93,
                        "end": 105,
                        "callee": {
                            "type": "Identifier",
                            "start": 93,
                            "end": 96,
                            "name": "log"
                        },
                        "arguments": [
                            {
                                "type": "Literal",
                                "start": 97,
                                "end": 104,
                                "value": "Awful",
                                "raw": "'Awful'"
                            }
                        ]
                    }
                }
            ]
        }
    }
}
xvno commented 4 years ago
1.2.2 ConditionalExpression
a > -1 ? log('Positive') : (a > -2) ? log('Not too bad') : log('Awful');
{
    "type": "ExpressionStatement",
    "start": 0,
    "end": 72,
    "expression": {
        "type": "ConditionalExpression",
        "start": 0,
        "end": 71,
        "test": {
            "type": "BinaryExpression",
            "start": 0,
            "end": 6,
            "left": {
                "type": "Identifier",
                "start": 0,
                "end": 1,
                "name": "a"
            },
            "operator": ">",
            "right": {
                "type": "UnaryExpression",
                "start": 4,
                "end": 6,
                "operator": "-",
                "prefix": true,
                "argument": {
                    "type": "Literal",
                    "start": 5,
                    "end": 6,
                    "value": 1,
                    "raw": "1"
                }
            }
        },
        "consequent": {
            "type": "CallExpression",
            "start": 9,
            "end": 24,
            "callee": {
                "type": "Identifier",
                "start": 9,
                "end": 12,
                "name": "log"
            },
            "arguments": [
                {
                    "type": "Literal",
                    "start": 13,
                    "end": 23,
                    "value": "Positive",
                    "raw": "'Positive'"
                }
            ]
        },
        "alternate": {
            "type": "ConditionalExpression",
            "start": 27,
            "end": 71,
            "test": {
                "type": "BinaryExpression",
                "start": 28,
                "end": 34,
                "left": {
                    "type": "Identifier",
                    "start": 28,
                    "end": 29,
                    "name": "a"
                },
                "operator": ">",
                "right": {
                    "type": "UnaryExpression",
                    "start": 32,
                    "end": 34,
                    "operator": "-",
                    "prefix": true,
                    "argument": {
                        "type": "Literal",
                        "start": 33,
                        "end": 34,
                        "value": 2,
                        "raw": "2"
                    }
                }
            },
            "consequent": {
                "type": "CallExpression",
                "start": 38,
                "end": 56,
                "callee": {
                    "type": "Identifier",
                    "start": 38,
                    "end": 41,
                    "name": "log"
                },
                "arguments": [
                    {
                        "type": "Literal",
                        "start": 42,
                        "end": 55,
                        "value": "Not too bad",
                        "raw": "'Not too bad'"
                    }
                ]
            },
            "alternate": {
                "type": "CallExpression",
                "start": 59,
                "end": 71,
                "callee": {
                    "type": "Identifier",
                    "start": 59,
                    "end": 62,
                    "name": "log"
                },
                "arguments": [
                    {
                        "type": "Literal",
                        "start": 63,
                        "end": 70,
                        "value": "Awful",
                        "raw": "'Awful'"
                    }
                ]
            }
        }
    }
}
xvno commented 4 years ago

1.3 for循环: for, for-in, for-of

  1. ForStatement: {init, test, update, body}
  2. ForInStatement: {left, right, body}
  3. ForOfStatement: {left, right, body}
xvno commented 4 years ago
1.3.1 ForStatement: {init, test, update, body}
for (let i = 0; i < n; i++) {
    log(i);
}
{
    "type": "ForStatement",
    "start": 0,
    "end": 43,
    "init": {
        "type": "VariableDeclaration",
        "start": 5,
        "end": 14,
        "declarations": [
            {
                "type": "VariableDeclarator",
                "start": 9,
                "end": 14,
                "id": {
                    "type": "Identifier",
                    "start": 9,
                    "end": 10,
                    "name": "i"
                },
                "init": {
                    "type": "Literal",
                    "start": 13,
                    "end": 14,
                    "value": 0,
                    "raw": "0"
                }
            }
        ],
        "kind": "let"
    },
    "test": {
        "type": "BinaryExpression",
        "start": 16,
        "end": 21,
        "left": {
            "type": "Identifier",
            "start": 16,
            "end": 17,
            "name": "i"
        },
        "operator": "<",
        "right": {
            "type": "Identifier",
            "start": 20,
            "end": 21,
            "name": "n"
        }
    },
    "update": {
        "type": "UpdateExpression",
        "start": 23,
        "end": 26,
        "operator": "++",
        "prefix": false,
        "argument": {
            "type": "Identifier",
            "start": 23,
            "end": 24,
            "name": "i"
        }
    },
    "body": {
        "type": "BlockStatement",
        "start": 28,
        "end": 43,
        "body": [
            {
                "type": "ExpressionStatement",
                "start": 34,
                "end": 41,
                "expression": {
                    "type": "CallExpression",
                    "start": 34,
                    "end": 40,
                    "callee": {
                        "type": "Identifier",
                        "start": 34,
                        "end": 37,
                        "name": "log"
                    },
                    "arguments": [
                        {
                            "type": "Identifier",
                            "start": 38,
                            "end": 39,
                            "name": "i"
                        }
                    ]
                }
            }
        ]
    }
}
xvno commented 4 years ago
1.3.2 for-in: ForInStatement: {left, right, body}
for(let k in o) {
  log(o[k]);
}
{
    "type": "ForInStatement",
    "start": 0,
    "end": 18,
    "left": {
        "type": "VariableDeclaration",
        "start": 4,
        "end": 9,
        "declarations": [
            {
                "type": "VariableDeclarator",
                "start": 8,
                "end": 9,
                "id": {
                    "type": "Identifier",
                    "start": 8,
                    "end": 9,
                    "name": "k"
                },
                "init": null
            }
        ],
        "kind": "let"
    },
    "right": {
        "type": "Identifier",
        "start": 13,
        "end": 14,
        "name": "o"
    },
    "body": {
        "type": "BlockStatement",
        "start": 16,
        "end": 18,
        "body": []
    }
}
for(let [k, v] in o) {}
{
    "type": "ForInStatement",
    "start": 0,
    "end": 23,
    "left": {
        "type": "VariableDeclaration",
        "start": 4,
        "end": 14,
        "declarations": [
            {
                "type": "VariableDeclarator",
                "start": 8,
                "end": 14,
                "id": {
                    "type": "ArrayPattern",
                    "start": 8,
                    "end": 14,
                    "elements": [
                        {
                            "type": "Identifier",
                            "start": 9,
                            "end": 10,
                            "name": "k"
                        },
                        {
                            "type": "Identifier",
                            "start": 12,
                            "end": 13,
                            "name": "v"
                        }
                    ]
                },
                "init": null
            }
        ],
        "kind": "let"
    },
    "right": {
        "type": "Identifier",
        "start": 18,
        "end": 19,
        "name": "o"
    },
    "body": {
        "type": "BlockStatement",
        "start": 21,
        "end": 23,
        "body": []
    }
} 
xvno commented 4 years ago
1.3.3 ForOfStatement: {left, right, body}
for(let i of arr) {}
{
    "type": "ForOfStatement",
    "start": 0,
    "end": 20,
    "await": false,
    "left": {
        "type": "VariableDeclaration",
        "start": 4,
        "end": 9,
        "declarations": [
            {
                "type": "VariableDeclarator",
                "start": 8,
                "end": 9,
                "id": {
                    "type": "Identifier",
                    "start": 8,
                    "end": 9,
                    "name": "i"
                },
                "init": null
            }
        ],
        "kind": "let"
    },
    "right": {
        "type": "Identifier",
        "start": 13,
        "end": 16,
        "name": "arr"
    },
    "body": {
        "type": "BlockStatement",
        "start": 18,
        "end": 20,
        "body": []
    }
}
xvno commented 4 years ago

1.4 while, do-while

  1. WhileStatement: {test:{left, operator, right}, body}
  2. DoWhileStatement
xvno commented 4 years ago
1.4.1 WhileStatement: {test, body}
while(i < n) {
    i++;
}
{
    "type": "WhileStatement",
    "start": 0,
    "end": 22,
    "test": {
        "type": "BinaryExpression",
        "start": 6,
        "end": 11,
        "left": {
            "type": "Identifier",
            "start": 6,
            "end": 7,
            "name": "i"
        },
        "operator": "<",
        "right": {
            "type": "Identifier",
            "start": 10,
            "end": 11,
            "name": "n"
        }
    },
    "body": {
        "type": "BlockStatement",
        "start": 13,
        "end": 22,
        "body": [
            {
                "type": "ExpressionStatement",
                "start": 16,
                "end": 20,
                "expression": {
                    "type": "UpdateExpression",
                    "start": 16,
                    "end": 19,
                    "operator": "++",
                    "prefix": false,
                    "argument": {
                        "type": "Identifier",
                        "start": 16,
                        "end": 17,
                        "name": "i"
                    }
                }
            }
        ]
    }
}
xvno commented 4 years ago
1.4.2 DoWhileStatement: {body, test{left, operator, right}}
do{
  i++;
}while(i < n)
{
    "type": "DoWhileStatement",
    "start": 24,
    "end": 48,
    "body": {
        "type": "BlockStatement",
        "start": 26,
        "end": 36,
        "body": [
            {
                "type": "ExpressionStatement",
                "start": 30,
                "end": 34,
                "expression": {
                    "type": "UpdateExpression",
                    "start": 30,
                    "end": 33,
                    "operator": "++",
                    "prefix": false,
                    "argument": {
                        "type": "Identifier",
                        "start": 30,
                        "end": 31,
                        "name": "i"
                    }
                }
            }
        ]
    },
    "test": {
        "type": "BinaryExpression",
        "start": 42,
        "end": 47,
        "left": {
            "type": "Identifier",
            "start": 42,
            "end": 43,
            "name": "i"
        },
        "operator": "<",
        "right": {
            "type": "Identifier",
            "start": 46,
            "end": 47,
            "name": "n"
        }
    }
}
xvno commented 4 years ago

1.5 switch: SwitchStatement

discriminant: 带检参数 cases[]: SwitchCase-consequent[ExpressionStatement, BreakStatement] default: test:null, default是test为null的特殊case

switch(n) {
  case i:
    log(i);
    break;
  case 1:
  default:
    n << 1;
}
{
    "type": "SwitchStatement",
    "start": 0,
    "end": 76,
    "discriminant": {
        "type": "Identifier",
        "start": 7,
        "end": 8,
        "name": "n"
    },
    "cases": [
        {
            "type": "SwitchCase",
            "start": 14,
            "end": 44,
            "consequent": [
                {
                    "type": "ExpressionStatement",
                    "start": 26,
                    "end": 33,
                    "expression": {
                        "type": "CallExpression",
                        "start": 26,
                        "end": 32,
                        "callee": {
                            "type": "Identifier",
                            "start": 26,
                            "end": 29,
                            "name": "log"
                        },
                        "arguments": [
                            {
                                "type": "Identifier",
                                "start": 30,
                                "end": 31,
                                "name": "i"
                            }
                        ]
                    }
                },
                {
                    "type": "BreakStatement",
                    "start": 38,
                    "end": 44,
                    "label": null
                }
            ],
            "test": {
                "type": "Identifier",
                "start": 19,
                "end": 20,
                "name": "i"
            }
        },
        {
            "type": "SwitchCase",
            "start": 47,
            "end": 54,
            "consequent": [],
            "test": {
                "type": "Literal",
                "start": 52,
                "end": 53,
                "name": "1"
            }
        },
        {
            "type": "SwitchCase",
            "start": 57,
            "end": 74,
            "consequent": [
                {
                    "type": "ExpressionStatement",
                    "start": 67,
                    "end": 74,
                    "expression": {
                        "type": "BinaryExpression",
                        "start": 67,
                        "end": 73,
                        "left": {
                            "type": "Identifier",
                            "start": 67,
                            "end": 68,
                            "name": "n"
                        },
                        "operator": "<<",
                        "right": {
                            "type": "Literal",
                            "start": 72,
                            "end": 73,
                            "value": 1,
                            "raw": "1"
                        }
                    }
                }
            ],
            "test": null
        }
    ]
}
xvno commented 4 years ago

1.6 Function: Declaration, Invoking

Declaration:

Invoking:

xvno commented 4 years ago
1.6.1 FunctionDeclaration, FunctionExpression
function fn(){
    log(arguments); 
}
{
    "type": "FunctionDeclaration",
    "start": 0,
    "end": 34,
    "id": {
        "type": "Identifier",
        "start": 9,
        "end": 11,
        "name": "fn"
    },
    "expression": false,
    "generator": false,
    "async": false,
    "params": [],
    "body": {
        "type": "BlockStatement",
        "start": 13,
        "end": 34,
        "body": [
            {
                "type": "ExpressionStatement",
                "start": 16,
                "end": 31,
                "expression": {
                    "type": "CallExpression",
                    "start": 16,
                    "end": 30,
                    "callee": {
                        "type": "Identifier",
                        "start": 16,
                        "end": 19,
                        "name": "log"
                    },
                    "arguments": [
                        {
                            "type": "Identifier",
                            "start": 20,
                            "end": 29,
                            "name": "arguments"
                        }
                    ]
                }
            }
        ]
    }
}
var fn = function (){
    log(arguments); 
}
{
    "type": "VariableDeclaration",
    "start": 0,
    "end": 41,
    "declarations": [
        {
            "type": "VariableDeclarator",
            "start": 4,
            "end": 41,
            "id": {
                "type": "Identifier",
                "start": 4,
                "end": 6,
                "name": "fn"
            },
            "init": {
                "type": "FunctionExpression",
                "start": 9,
                "end": 41,
                "id": null,
                "expression": false,
                "generator": false,
                "async": false,
                "params": [],
                "body": {
                    "type": "BlockStatement",
                    "start": 20,
                    "end": 41,
                    "body": [
                        {
                            "type": "ExpressionStatement",
                            "start": 23,
                            "end": 38,
                            "expression": {
                                "type": "CallExpression",
                                "start": 23,
                                "end": 37,
                                "callee": {
                                    "type": "Identifier",
                                    "start": 23,
                                    "end": 26,
                                    "name": "log"
                                },
                                "arguments": [
                                    {
                                        "type": "Identifier",
                                        "start": 27,
                                        "end": 36,
                                        "name": "arguments"
                                    }
                                ]
                            }
                        }
                    ]
                }
            }
        }
    ],
    "kind": "var"
}
xvno commented 4 years ago
1.6.2 Function Invoking(callee): CallExpression
fn(1, 'a', [1,2], {name: 'vno'}, fn);
{
    "type": "ExpressionStatement",
    "start": 0,
    "end": 36,
    "expression": {
        "type": "CallExpression",
        "start": 0,
        "end": 36,
        "callee": {
            "type": "Identifier",
            "start": 0,
            "end": 2,
            "name": "fn"
        },
        "arguments": [
            {
                "type": "Literal",
                "start": 3,
                "end": 4,
                "value": 1,
                "raw": "1"
            },
            {
                "type": "Literal",
                "start": 6,
                "end": 9,
                "value": "a",
                "raw": "'a'"
            },
            {
                "type": "ArrayExpression",
                "start": 11,
                "end": 16,
                "elements": [
                    {
                        "type": "Literal",
                        "start": 12,
                        "end": 13,
                        "value": 1,
                        "raw": "1"
                    },
                    {
                        "type": "Literal",
                        "start": 14,
                        "end": 15,
                        "value": 2,
                        "raw": "2"
                    }
                ]
            },
            {
                "type": "ObjectExpression",
                "start": 18,
                "end": 31,
                "properties": [
                    {
                        "type": "Property",
                        "start": 19,
                        "end": 30,
                        "method": false,
                        "shorthand": false,
                        "computed": false,
                        "key": {
                            "type": "Identifier",
                            "start": 19,
                            "end": 23,
                            "name": "name"
                        },
                        "value": {
                            "type": "Literal",
                            "start": 25,
                            "end": 30,
                            "value": "vno",
                            "raw": "'vno'"
                        },
                        "kind": "init"
                    }
                ]
            },
            {
                "type": "Identifier",
                "start": 33,
                "end": 35,
                "name": "fn"
            }
        ]
    }
}