eval5 - 基於JavaScript編寫的JavaScript解釋器

背景

因爲以前項目中爲了最求最大靈活度,部分功能預留了JavaScript腳本配置入口,若有特殊需求的狀況下可不修改代碼實現個性化需求。
例如:報表設計中的圖形組件,可能不一樣的報表展現形式多樣,此時的界面配置沒法提早預設全部可能的狀況,若是在圖形渲染將前端生成的配置參數交給預先配置好的JavaScript腳本進行特殊處理就能夠完成個性需求。但該功能須要動態執行JavaScript腳本,前端只能經過eval Function方式來動態執行,這種運行方式在瀏覽器模式下是沒問題,但在不支持eval Function的運行環境就沒法實現上述需求,例如:微信小程序。前端

eval5是徹底基於JavaScript編寫的JavaScript解釋器,支持ECMA5語法。node

項目地址:https://github.com/bplok20010...git

在線體驗:https://bplok20010.github.io/...github

運行原理

步驟一:eval5先經過acorn將源碼編譯獲得樹狀結構的抽象語法樹(AST)express

抽象語法樹由不一樣的節點組成,每一個節點的type標識着不一樣的語句或表達式,例如: 1+1的抽象語法樹:
{
    "type": "Program",
    "body": [
        {
            "type": "ExpressionStatement",
            "expression": {
                "type": "BinaryExpression",
                "operator": "+",
                "left": {
                    "type": "Literal",
                    "value": 1,
                    "raw": "1"
                },
                "right": {
                    "type": "Literal",
                    "value": 1,
                    "raw": "1"
                }
            }
        }
    ],
    "sourceType": "script"
}

步驟二:爲不一樣的節點type編寫不一樣的處理模塊並獲得最終結果。例如:根據1+1的語法樹咱們能夠寫出一下解釋器代碼:npm

function handleBinaryExpression(node) {
    switch( node.operator ) {
        case '+':
            return node.left.value + node.right.value;
        case '-':
            return node.left.value - node.right.value;
    }
}

運行原理.png

生成 抽象語法樹這一步已經有不少優秀的開源庫,如: esprima acorn babylon ...

步驟二執行大概以下:小程序

  1. 先遍歷語法樹,找出函數聲明及變量聲明,由於有做用域提高。
  2. 開始執行語句或表達式,創建做用域。(此步驟很是關鍵)
  3. 根據不一樣的語法節點type執行對應的處理方法,並獲得最後一個表達式返回值。例如BinaryExpression節點則調用handleBinaryExpression方法
更多實現細節就不詳細講解,有興趣的可直接到github上看 源碼

須要注意的兩點:微信小程序

  • 做用域處理
  • 函數建立及調用

運行效果

可將es5代碼直接粘貼到文章開頭的體驗地址並運行查看效果。如下是運行echarts的效果示例:瀏覽器

  1. 複製https://cdn.jsdelivr.net/npm/... 代碼到在線體驗中運行。
  2. 複製如下echart代碼並運行
//設置在線體驗容器高度
root.style.height = '300px';
// 基於準備好的dom,初始化echarts實例
var myChart = echarts.init(document.getElementById('root'));
// 指定圖表的配置項和數據
var option = {
    title: {
        text: 'ECharts 入門示例'
    },
    tooltip: {},
    legend: {
        data: ['銷量']
    },
    xAxis: {
        data: ["襯衫", "羊毛衫", "雪紡衫", "褲子", "高跟鞋", "襪子"]
    },
    yAxis: {},
    series: [{
        name: '銷量',
        type: 'bar',
        data: [5, 20, 36, 10, 10, 20]
    }]
};
// 使用剛指定的配置項和數據顯示圖表。
myChart.setOption(option);

效果如圖:
效果.png微信

使用場景

不支持eval Function的運行環境,例如:微信小程序,小程序開發用戶可直接看這篇介紹:小程序eval/Function終極替代方案:eval5

相關文章
相關標籤/搜索