这可能不是您要查找的内容,但如果不是将字符串传递给您的沙箱,而是传递一个函数会怎样。这甚至允许将eval 用于源文件。
您的代码将像这样工作:
...
Sandbox.prototype.Run = function(fn){
fn.call(this);
}
var bx = new Sandbox();
bx.run(function(){
this.x = 1;
});
bx.getVar("x") // 1
如果你想使用eval,你只需要编写一个函数来附加函数语法
/* source.js */
this.x = 1;
this.blah = "Hello, World!";
与:
Sandbox.prototype.evaluate = function(src){
return eval("function(){" + src + "}");
}
bx.Run(Sandbox.evaluate(src));
bx.getVar("x") // 1
bx.getVar("blah") // "Hello, World!"
同样使用此方法,您可以将沙盒代码对象和函数传递给要使用的函数,该函数将模拟一个全新的伪环境以供使用。
编辑:我对您的问题的完美答案做了一些研究,即
我可以遍历在本地范围内声明的变量吗?
答案是no (StackOverflow)。目前看来这是javascript的限制。希望新规范中会出现类似的内容。
我目前的想法是评估源以使所有 var 语句都转到 window 对象,通过一些努力,可以迭代并添加到 Sandbox 对象手动。
像这样警告:非常简化
(function(){
var src = get_source_file();
eval(src);
iterate_over_each_newly_created_window_property(function(property, value){
bx[property] = value;
window[property] = undefined;
});
})();
编辑 2:
我的想法可行 =)
function Sandbox(){
return this;
}
Sandbox.prototype.run = function(src){
// Take a snapshopt of the window object before
var before = {};
var prop;
for(prop in window){
before[prop] = true;
}
// Then evaluate the source
window.eval(src);
// Then see what changed
var changed = [];
for(prop in window){
if(!before[prop]){
// Add to the sandbox object
this[prop] = window[prop];
delete window[prop];
}
}
}
var bx = new Sandbox();
bx.run("var x = 'Hello, World!';");
alert(bx.x);
A working example (jsFiddle)
function Sandbox(){
this.keys = [];
this.values = [];
return this;
}
Sandbox.prototype.eval = function(src){
var before = {}, prop, fn;
// Take a snapshopt of the window object before
src = "function(" + this.keys.join(",") + "){" + src + "}";
src = src.replace(/var/g, "");
/* I'm not a wisard at regex so a better one should be used avoid this bug
var x, y, z; */
for(prop in window){
before[prop] = true;
}
// Then evaluate the source
fn = window.eval(src);
fn.apply(window, this.values);
// Then see what changed
for(prop in window){
if(!before[prop]){
// Add to the sandbox object
this.keys.push(prop);
this.values.push(window[prop]);
this[prop] = window[prop];
delete window[prop];
}
}
}
var bx = new Sandbox();
bx.eval("var x = 1;");
bx.eval("var y = x;");
alert(bx.x);
alert(bx.y);
编辑 3:修复错误 to your specifications
现在我知道其中存在错误以及一些可能使其失控的功能。现在,清理代码以供实际使用是您的工作。我从概念上给了你如何做到这一点。