我有一系列指令,如下所示:
[
{"name": "a", "expr": "1"},
{"name": "b", "expr": "4"},
{"name": "c", "expr": "a * b + 100"},
{"name": "a", "expr": "a - 5"}
]
我想使用在浏览器中运行的JavaScript引擎执行它们,然后访问结果。
显然,首先尝试尝试只是
eval(inst.name + " = " + inst.expr);
事实上,它可行,但它会污染全局window
命名空间并冒着冲突的风险。
这是我到目前为止所拥有的:
var Memory = (function() {
function Memory() {}
Memory.prototype.evalExpr = function(expr) {
return eval(expr);
};
return Memory;
})();
var mem = new Memory();
然后使用:
执行每条指令inst
mem[inst.name] = mem.evalExpr(inst.expr);
这是半工作的,但我必须更改所有指令以在this.
之前添加所有变量名,即:
[
{"name": "a", "expr": "1"},
{"name": "b", "expr": "4"},
{"name": "c", "expr": "this.a * this.b + 100"},
{"name": "a", "expr": "this.a - 5"}
]
是否有任何快速方法可以以不需要将this.
添加到变量名称的方式对对象执行读取操作?正确地修改表达式需要构建一个成熟的表达式解析器 - 换句话说,只需将像jison这样的相对较重的库插入到项目中就更容易了,并尝试使用它。
这与其他“沙盒JavaScript评估”问题略有不同,如:
我真的不需要正确的沙盒,我执行的代码足够可信,我只想将所有这些结果变量放在一个隔离的空间中(例如,轻松地对JSON.stringify
进行操作稍后等)。
这个在浏览器中处理JavaScript引擎,而不是像node.js这样的独立引擎。
答案 0 :(得分:0)
此问题的基础不是沙盒,而是如何在JavaScript中访问给定对象(例如a
)的属性(即b
,mem
,...)作为局部变量,即没有任何前缀,如this.a
或mem.a
。
结果是解决方案是臭名昭着的with
statement(就像eval
一样,有些人经常"considered harmful"。但是,在这种情况下,它可以完美地完成工作:可以用它动态地评估任意表达式:
function VM() {
this.mem = {};
}
VM.prototype.varSet = function(varName, expr) {
var _t;
with (this.mem) { _t = eval(expr) };
this.mem[varName] = _t;
};
vm = new VM()
因此,执行指令很容易:
insts.forEach(function(inst) {
vm.varSet(inst.name, inst.expr);
});
获得个人结果:
vm.mem.a // => -4
并将所有结果合并为正确的纯JavaScript对象,例如,导出为JSON字符串:
JSON.stringify(vm.mem) // => "{\"a\":-4,\"b\":4,\"c\":104}"