webpack
和Lint
等不少的工具和庫的核心都是經過Abstract Syntax Tree
抽象語法樹這個概念來實現對代碼的檢查、分析等操做的node
這些工具的原理都是經過JavaScript Parser
把代碼轉化爲一顆抽象語法樹(AST),這顆樹定義了代碼的結構,經過操縱這顆樹,咱們能夠精準的定位到聲明語句、賦值語句、運算語句等等,實現對代碼的分析、優化、變動等操做webpack
在計算機科學中,抽象語法樹(abstract syntax tree或者縮寫爲AST),或者語法樹(syntax tree),是源代碼的抽象語法結構的樹狀表現形式,這裏特指編程語言的源代碼。web
Javascript的語法是爲了給開發者更好的編程而設計的,可是不適合程序的理解。因此須要轉化爲AST來使之更適合程序分析,瀏覽器編譯器通常會把源碼轉化爲AST來進行進一步的分析等其餘操做。 JavaScript Parserexpress
JavaScript Parser,把js源碼轉化爲抽象語法樹的解析器。npm
瀏覽器會把js源碼經過解析器轉爲抽象語法樹,再進一步轉化爲字節碼或直接生成機器碼。編程
通常來講每一個js引擎都會有本身的抽象語法樹格式,Chrome的v8引擎,firefox的SpiderMonkey引擎等等,MDN提供了詳細SpiderMonkey AST format的詳細說明,算是業界的標準。瀏覽器
接下來咱們將下面代碼轉換成AST,而後生成先的函數newAstbash
let code = 'function ast(){}'; //js代碼便可(字符串形式)async
esprima
estraverse
escodegen
npm i esprima estraverse escodegen -D
複製代碼
把上面的源碼轉成AST編程語言
// 把源碼轉化爲AST
let ast = esprima.parseModule(code);
console.log(ast);
複製代碼
打印結果以下 Module { type: 'Program', body: [ FunctionDeclaration { type: 'FunctionDeclaration', id: [Object], params: [], body: [Object], generator: false, expression: false, async: false } ], sourceType: 'module' }
複製代碼
let indent = 0;
function padding() {
return " ".repeat(indent);
}
estraverse.traverse(ast, {
enter(node) {
//進入
console.log(padding() + node.type + "進入");
if (node.type === "FunctionDeclaration") {
node.id.name = "newAst";
}
indent += 2;
},
leave(node) {
//離開
indent -= 2;
console.log(padding() + node.type + "退出");
},
});
複製代碼
打印結果
Program進入
FunctionDeclaration進入
Identifier進入
Identifier退出
BlockStatement進入
BlockStatement退出
FunctionDeclaration退出
Program退出
複製代碼
最後,把修改後的抽象語法從新生成源代碼
//把修改事後的抽象語法樹從新生成源代碼
let result = escodegen.generate(ast);
console.log(result);
複製代碼
打印後的結果
function newAst() {
}
複製代碼