1. 90前端首页
  2. 前端开发
  3. JavaScript

eval5 - 基于JavaScript编写的JavaScript解释器

背景

由于之前项目中为了最求最大灵活度,部分功能预留了JavaScript脚本配置入口,如有特殊需求的情况下可不修改代码实现个性化需求。
例如:报表设计中的图形组件,可能不同的报表展示形式多样,此时的界面配置无法提前预设所有可能的情况,如果在图形渲染将前端生成的配置参数交给预先配置好的JavaScript脚本进行特殊处理就可以完成个性需求。但该功能需要动态执行JavaScript脚本,前端只能通过eval Function方式来动态执行,这种运行方式在浏览器模式下是没问题,但在不支持eval Function的运行环境就无法实现上述需求,例如:微信小程序。

eval5是完全基于JavaScript编写的JavaScript解释器,支持ECMA5语法。

项目地址:https://github.com/bplok20010...

在线体验:https://bplok20010.github.io/...

运行原理

步骤一:eval5先通过acorn将源码编译得到树状结构的抽象语法树(AST)

抽象语法树由不同的节点组成,每个节点的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的语法树我们可以写出一下解释器代码:

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

eval5 - 基于JavaScript编写的JavaScript解释器

生成抽象语法树这一步已经有很多优秀的开源库,如: 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);      

效果如图:
eval5 - 基于JavaScript编写的JavaScript解释器

使用场景

不支持eval Function的运行环境,例如:微信小程序,小程序开发用户可直接看这篇介绍:小程序eval/Function终极替代方案:eval5

本文来自网络整理,转载请注明原出处:https://segmentfault.com/a/1190000021690840

展开阅读全文

发表评论

登录后才能评论