成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

一看就懂的JS抽象語(yǔ)法樹(shù)

HackerShell / 3340人閱讀

摘要:前言是現(xiàn)在幾乎每個(gè)項(xiàng)目中必備的一個(gè)東西,但是其工作原理避不開(kāi)對(duì)的解析在生成的過(guò)程,有引擎,早期了項(xiàng)目,了解這個(gè)之前我們先來(lái)看看這種引擎解析出來(lái)是什么東西。

前言

babel是現(xiàn)在幾乎每個(gè)項(xiàng)目中必備的一個(gè)東西,但是其工作原理避不開(kāi)對(duì)js的解析在生成的過(guò)程,babel有引擎babylon,早期fork了項(xiàng)目acron,了解這個(gè)之前我們先來(lái)看看這種引擎解析出來(lái)是什么東西。不光是babel還有webpack等都是通過(guò)javascript parser將代碼轉(zhuǎn)化成抽象語(yǔ)法樹(shù),這棵樹(shù)定義了代碼本身,通過(guò)操作這顆樹(shù),可以精準(zhǔn)的定位到賦值語(yǔ)句、聲明語(yǔ)句和運(yùn)算語(yǔ)句

什么是抽象語(yǔ)法樹(shù)

我們可以來(lái)看一個(gè)簡(jiǎn)單的例子:

var a = 1;
var b = a + 1;

我們通過(guò)這個(gè)網(wǎng)站,他是一個(gè)esprima引擎的網(wǎng)站,十分好用.畫(huà)成流程圖如下:

而他的json對(duì)象格式是這樣的:

{
    "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.還有一些常用的引擎有:

esprima

acron

Traceur

UglifyJS2

shift

下面是一些引擎的速度對(duì)比,以及用不同的框架,引擎?zhèn)兊募虞d速度:

我個(gè)人認(rèn)為,封裝的越完美的,其實(shí)解析的時(shí)間更長(zhǎng),引擎之間也是acron這個(gè)速度比較優(yōu)秀,babel引擎前身就是fork這個(gè)項(xiàng)目的。

AST的三板斧

通過(guò)esprima生成AST

通過(guò)estraverse遍歷和更新AST

通過(guò)escodegen將AST重新生成源碼

我們可以來(lái)做一個(gè)簡(jiǎn)單的例子:

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

npm i esprima estraverse escodegen --save

3.在目錄下面新建一個(gè)test.js文件,載入以下代碼:

const esprima = require("esprima");
let code = "const a = 1";
const ast = esprima.parseScript(code);
console.log(ast);

你將會(huì)看到輸出結(jié)果:

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);

輸出的結(jié)果:

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);

輸出的結(jié)果:

var a = 1;

通過(guò)這三板斧:我們將const a = 1轉(zhuǎn)化成了var a = 1

有沒(méi)有babel的感覺(jué)0.0

推薦網(wǎng)站

esprima源碼
acron源碼
speed comparison
AST explorer
esprima可視化
在線可視化AST

總結(jié)

抽象樹(shù)在前端用的很多很多,現(xiàn)在流行的工具,不管是webpack還是babel都會(huì)通過(guò)那個(gè)三板斧的流程,這里我只是大致介紹一下,過(guò)段時(shí)間,會(huì)出一篇抽象樹(shù)的語(yǔ)法,有興趣的也可以把esprima的源碼看一下,為什么是esprima呢,因?yàn)閑sprima的資料比較多,而acron比較輕量級(jí)。有興趣的可以關(guān)注一下我的[github](),記得點(diǎn)個(gè)star,就當(dāng)是對(duì)筆者的支持,謝謝。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/92696.html

相關(guān)文章

  • 一看懂的module.exports/exports與module.export/export d

    摘要:命令規(guī)定的是對(duì)外的接口,必須與模塊內(nèi)部的變量建立一一對(duì)應(yīng)關(guān)系。意思是導(dǎo)出的不是一個(gè)具體的數(shù)值,而是一個(gè)對(duì)象命令接受一對(duì)大括號(hào),里面指定要從其他模塊導(dǎo)入的變量名。大括號(hào)里面的變量名,必須與被導(dǎo)入模塊對(duì)外接口的名稱相同。 一、module.exports與exports nodeJS采用commonJs規(guī)范,當(dāng)前文件是一個(gè)模塊(module)私有域,通過(guò)exports屬性導(dǎo)出,通過(guò)re...

    ZoomQuiet 評(píng)論0 收藏0
  • 一看懂的例子告訴你用react-redux的正確姿勢(shì)

    摘要:很多小白在看過(guò)很多教程之后仍然在敲代碼的時(shí)候不清楚應(yīng)該以什么樣的步驟進(jìn)行,那么這篇文章就一步一步分解整個(gè)過(guò)程,慢動(dòng)作回放讓大家看的清清楚楚明明白白。另外,中視圖部分最好單獨(dú)出來(lái),放在新建一個(gè)文件夾目錄下,并被名為引用,把其他邏輯部分放后者。 whay write this: 很多小白在看過(guò)很多教程之后仍然在敲代碼的時(shí)候不清楚應(yīng)該以什么樣的步驟進(jìn)行,那么這篇文章就一步一步分解整個(gè)過(guò)程,慢...

    DobbyKim 評(píng)論0 收藏0
  • 一看懂的javascript全等于與等于

    Javascript只有六個(gè)假值(用在條件if的判斷) showImg(https://segmentfault.com/img/bVLiHL?w=424&h=346); 全等于 類型不同,返回false類型相同,則 showImg(https://segmentfault.com/img/bVLiHS?w=476&h=341); 等于 類型相同:同上=== 類型不同:嘗試類型轉(zhuǎn)換==【不是真值和...

    Apollo 評(píng)論0 收藏0
  • 一看懂的Java線程池分析詳解

    摘要:任務(wù)性質(zhì)不同的任務(wù)可以用不同規(guī)模的線程池分開(kāi)處理。線程池在運(yùn)行過(guò)程中已完成的任務(wù)數(shù)量。如等于線程池的最大大小,則表示線程池曾經(jīng)滿了。線程池的線程數(shù)量。獲取活動(dòng)的線程數(shù)。通過(guò)擴(kuò)展線程池進(jìn)行監(jiān)控??蚣馨ň€程池,,,,,,等。 Java線程池 [toc] 什么是線程池 線程池就是有N個(gè)子線程共同在運(yùn)行的線程組合。 舉個(gè)容易理解的例子:有個(gè)線程組合(即線程池,咱可以比喻為一個(gè)公司),里面有3...

    Yangder 評(píng)論0 收藏0
  • 實(shí)現(xiàn)一個(gè)簡(jiǎn)易的webpack

    摘要:首先一段代碼轉(zhuǎn)化成的抽象語(yǔ)法樹(shù)是一個(gè)對(duì)象,該對(duì)象會(huì)有一個(gè)頂級(jí)的屬性第二個(gè)屬性是是一個(gè)數(shù)組。最終完成整個(gè)文件依賴的處理。參考文章抽象語(yǔ)法樹(shù)一看就懂的抽象語(yǔ)法樹(shù)源碼所有的源碼已經(jīng)上傳 背景 隨著前端復(fù)雜度的不斷提升,誕生出很多打包工具,比如最先的grunt,gulp。到后來(lái)的webpack和 Parcel。但是目前很多腳手架工具,比如vue-cli已經(jīng)幫我們集成了一些構(gòu)建工具的使用。有的時(shí)...

    darcrand 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

HackerShell

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<