一看就懂的JS抽象語法樹

前言

babel是如今幾乎每一個項目中必備的一個東西,可是其工做原理避不開對js的解析在生成的過程,babel有引擎babylon,早期fork了項目acron,瞭解這個以前咱們先來看看這種引擎解析出來是什麼東西。不光是babel還有webpack等都是經過javascript parser將代碼轉化成抽象語法樹,這棵樹定義了代碼自己,經過操做這顆樹,能夠精準的定位到賦值語句、聲明語句和運算語句。有興趣的能夠關注一下個人github,點一個star。謝謝javascript

什麼是抽象語法樹

咱們能夠來看一個簡單的例子:html

var a = 1;
var b = a + 1;
複製代碼

咱們經過這個網站,他是一個esprima引擎的網站,十分好用.畫成流程圖以下:前端

AST

而他的json對象格式是這樣的:java

{
    "type": "Program",
    "body": [
        {
            "type": "VariableDeclaration",
            "declarations": [
                {
                    "type": "VariableDeclarator",
                    "id": {
                        "type": "Identifier",
                        "name": "a"
                    },
                    "init": {
                        "type": "Literal",
                        "value": 1,
                        "raw": "1"
                    }
                }
            ],
            "kind": "var"
        },
        {
            "type": "VariableDeclaration",
            "declarations": [
                {
                    "type": "VariableDeclarator",
                    "id": {
                        "type": "Identifier",
                        "name": "b"
                    },
                    "init": {
                        "type": "BinaryExpression",
                        "operator": "+",
                        "left": {
                            "type": "Identifier",
                            "name": "a"
                        },
                        "right": {
                            "type": "Literal",
                            "value": 1,
                            "raw": "1"
                        }
                    }
                }
            ],
            "kind": "var"
        }
    ],
    "sourceType": "script"
}
複製代碼

衆多的引擎

chrome有v8,firefix有spidermonkey.還有一些經常使用的引擎有:node

  • esprima
  • acron
  • Traceur
  • UglifyJS2
  • shift

下面是一些引擎的速度對比,以及用不一樣的框架,引擎們的加載速度:react

jq-parser

ng-parser

react-parser

我我的認爲,封裝的越完美的,其實解析的時間更長,引擎之間也是acron這個速度比較優秀,babel引擎前身就是fork這個項目的。jquery

AST的三板斧

  • 經過esprima生成AST
  • 經過estraverse遍歷和更新AST
  • 經過escodegen將AST從新生成源碼

咱們能夠來作一個簡單的例子:webpack

1.先新建一個test的工程目錄 2.在test工程下安裝esprima、estraverse、escodegen的npm模塊git

npm i esprima estraverse escodegen --save
複製代碼

3.在目錄下面新建一個test.js文件,載入如下代碼:github

const esprima = require('esprima');
let code = 'const a = 1';
const ast = esprima.parseScript(code);
console.log(ast);
複製代碼

你將會看到輸出結果:

Script {
  type: 'Program',
  body:
   [ VariableDeclaration {
       type: 'VariableDeclaration',
       declarations: [Array],
       kind: 'const' } ],
  sourceType: 'script' }
複製代碼

4.再在test文件中,載入如下代碼:

const estraverse = require('estraverse');

estraverse.traverse(ast, {
    enter: function (node) {
        node.kind = "var";
    }
});

console.log(ast);
複製代碼

輸出的結果:

Script {
  type: 'Program',
  body:
   [ VariableDeclaration {
       type: 'VariableDeclaration',
       declarations: [Array],
       kind: 'var' } ],
  sourceType: 'script' }
複製代碼

5.最後在test文件中,加入如下代碼:

const escodegen = require("escodegen");
const transformCode = escodegen.generate(ast)

console.log(transformCode);

複製代碼

輸出的結果:

var a = 1;
複製代碼
  • 經過這三板斧:咱們將const a = 1轉化成了var a = 1

有沒有babel的感受0.0

推薦網站

esprima源碼

acron源碼

speed comparison

AST explorer

esprima可視化

在線可視化AST

總結

抽象樹在前端用的不少不少,如今流行的工具,無論是webpack仍是babel都會經過那個三板斧的流程,這裏我只是大體介紹一下,過段時間,會出一篇抽象樹的語法,有興趣的也能夠把esprima的源碼看一下,爲何是esprima呢,由於esprima的資料比較多,而acron比較輕量級。有興趣的能夠關注一下個人github,記得點個star,就當是對筆者的支持,謝謝。

相關文章
相關標籤/搜索