Eval一般不受欢迎,但似乎有必要。
目前,我有一个ajax调用,用于检索具有内联javascript的html文件。然后它通过标记名获取脚本并逐出它。
这一切都运作正常,但我无法弄清楚所有的变种都在哪里。
例如,在正常情况下,所有内容都可以在窗口中找到:
var you = "buddy"
alert(window["you"]);
//Alerts : "buddy"
但是当我做一个评估时,我不知道等同于什么窗口'是。我不确定所有的变量到底在哪里。
我想要的是获得所有这些列表的一些方法,而不会覆盖全局范围内存在的任何变量。
答案 0 :(得分:1)
eval
将共享全局上下文(window
)和任何局部变量。如果在全球范围内执行:
eval('var a=1; b=2');
console.log(window.a, window.b);
// => 1 2
new Function
将创建一个新的本地范围:
new Function('var c=7; d=4')()
console.log(window.c, window.d);
// => undefined 4
您可以将全局范围内的任何变量枚举为window
(或global
)的属性。您无法以任何方式枚举局部变量。
答案 1 :(得分:1)
如果直接调用eval()
,则它在本地范围内运行。因此,如果脚本定义了新变量,那么它们就在本地范围内定义。迭代本地范围变量没有内置方法,因为Javascript没有提供迭代本地范围内定义的变量的方法(除非本地范围恰好也是全局范围)。
如果您通过间接引用(例如:
)调用eval
var geval = eval;
geval("some code here");
然后,在全局范围内评估代码,并且脚本中定义的任何变量都将成为新的全局变量。
您可以看到此explained on MDN。
注意:strict
mode中的规则略有不同。
答案 2 :(得分:0)
如果你这样做
eval(console.log(this));
响应是全局窗口对象,因此本地的evals范围似乎无法访问。
编辑:最终结果是undefined
,如DJDavid98所示:
eval("console.log('call resulted in: "+console.log(this)+"')");
您可以通过几种方式使evals全局存储变量。第一个是引用eval(如@jfriend00所示),如下所示:
var geval = eval;
geval("some code here");
使变量成为全局变量的另一种方法是从前面删除var,如下所示:
eval("mrglobal = 'hey'; var local = 'can't find me'")
console.log(window["mrglobal"]); //outputs hey
console.log(window["local"]); //outputs undefined
了解这一点,可以找到更好的解决方案:
这里有一些输入和输出: INPUT:
var mrlocal = "hey neighbor";
mrglobal = "just passing through"
if(true) {
mrlocal = mrglobal
}
输出:
var window.evals[0].mrlocal = "hey neighbor";
mrglobal = "just passing through"
if(true) {
window.evals[0].mrlocal = mrglobal
}
对于函数:可以正则表达它们的eval,并为局部变量添加全局引用,如下所示:
var evalIndex = window.evals.length;
window.evals[evalIndex] = {};
var evalPrefix = "window.evals["+evalIndex+"].";
var localVars = [];
var scripts = initMe.getElementsByTagName("script");
for(var s = 0; s < scripts.length; s++) {
var rex = /(var.+(;|\n)|(\{(.|\n)+?\}))/g;
var localVarRex = scripts[s].innerHTML.match(rex);
for(i in localVarRex) {
var match = localVarRex[i];
if(match.charAt(0) != '{') {
var var_name = match.replace(/(var +|( ?)+=.+\n?)/g, '');
var_name = var_name.replace(/[\n\r]/g, '');
localVars.push(var_name);
}
}
}
console.log(localVars);
for(var s = 0; s < scripts.length; s++) {
var textToEval = scripts[s].innerHTML;
for(i in localVars) {
var match = localVars[i];
var replace = evalPrefix+match;
var rex = new RegExp("(var)?[^\.]"+match, "g");
textToEval = textToEval.replace(rex, function(replaceMe) {
var out = replaceMe;
if(replaceMe.charAt(0) != '.') {
console.log('match::"'+replaceMe+'"');
out = replace;
if(replaceMe.charAt(0) != 'v')
out = replaceMe.charAt(0)+replace;
}
return out;
});
eval(textToEval);
}
}
所以,通过这个技巧,你可以引入外部html,评估它的脚本,并保留所有局部变量。
答案 3 :(得分:0)
几年后,我终于找到了解决方法:
with (new Proxy()) { eval() }
我正在使用的代码库早已死了,但是该代理可以捕获所有内容。