为 eval 获取 "window" 对象,并列出所有变量? Javascript 内联评估 html
Getting the "window" object for an eval, and list all vars? Javascript eval inline html
Eval 通常不受欢迎,但似乎有必要。
目前,我有一个 ajax 调用可以检索具有内联 javascript 的 html 文件。然后它通过标记名获取脚本并对其进行评估。
一切正常,但我无法弄清楚所有变量的去向。
例如,在正常情况下,所有内容都可以在window:
中找到
var you = "buddy"
alert(window["you"]);
//Alerts : "buddy"
但是当我进行评估时,我不知道 'window' 的等价物是什么。我不确定所有变量的最终位置。
我想要的是某种获取所有变量列表的方法,而不需要任何变量覆盖全局范围内存在的变量。
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
)的属性。您不能以任何方式枚举局部变量。
如果您直接调用 eval()
,那么它会在本地范围内运行。因此,如果脚本定义了新变量,那么它们将在本地范围内定义。没有内置的方法来迭代局部范围变量,因为 Javascript 没有提供迭代局部范围内定义的变量的方法(除非局部范围恰好也是全局范围)。
如果您通过间接引用调用 eval
,例如:
var geval = eval;
geval("some code here");
然后,在全局范围内评估代码,脚本中定义的任何变量都成为新的全局变量。
你可以看到这个explained on MDN。
注意:strict
mode中的规则略有不同。
如果你这样做
eval(console.log(this));
响应是全局 window 对象,因此 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
了解这一点,可以找到更好的解决方案:
这是一些输入和输出:
输入:
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
}
对于函数:可以正则表达式计算他们将要求值的任何内容,并为局部变量添加全局引用,如下所示:
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,评估它的脚本,并保留所有局部变量。
多年后,我终于找到了解决方案:
with (new Proxy()) { eval() }
我正在处理的代码库早已失效,但该代理会捕获所有代码。
Eval 通常不受欢迎,但似乎有必要。
目前,我有一个 ajax 调用可以检索具有内联 javascript 的 html 文件。然后它通过标记名获取脚本并对其进行评估。
一切正常,但我无法弄清楚所有变量的去向。
例如,在正常情况下,所有内容都可以在window:
中找到var you = "buddy"
alert(window["you"]);
//Alerts : "buddy"
但是当我进行评估时,我不知道 'window' 的等价物是什么。我不确定所有变量的最终位置。
我想要的是某种获取所有变量列表的方法,而不需要任何变量覆盖全局范围内存在的变量。
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
)的属性。您不能以任何方式枚举局部变量。
如果您直接调用 eval()
,那么它会在本地范围内运行。因此,如果脚本定义了新变量,那么它们将在本地范围内定义。没有内置的方法来迭代局部范围变量,因为 Javascript 没有提供迭代局部范围内定义的变量的方法(除非局部范围恰好也是全局范围)。
如果您通过间接引用调用 eval
,例如:
var geval = eval;
geval("some code here");
然后,在全局范围内评估代码,脚本中定义的任何变量都成为新的全局变量。
你可以看到这个explained on MDN。
注意:strict
mode中的规则略有不同。
如果你这样做
eval(console.log(this));
响应是全局 window 对象,因此 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
了解这一点,可以找到更好的解决方案:
这是一些输入和输出: 输入:
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
}
对于函数:可以正则表达式计算他们将要求值的任何内容,并为局部变量添加全局引用,如下所示:
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,评估它的脚本,并保留所有局部变量。
多年后,我终于找到了解决方案:
with (new Proxy()) { eval() }
我正在处理的代码库早已失效,但该代理会捕获所有代码。