为 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,如 D​​JDavid98 所示:

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() }

我正在处理的代码库早已失效,但该代理会捕获所有代码。