获取 eval 的“窗口”对象,并列出所有变量?Javascript eval inline html.

Getting the "window" object for an eval, and list all vars? Javascript eval inline html

本文关键字:eval 变量 Javascript html inline 窗口 对象 获取      更新时间:2023-09-26

Eval通常不受欢迎,但似乎是必要的。

目前,我有一个 ajax 调用来检索具有内联 javascript 的 html 文件。 然后它按标签名获取脚本并对其进行评估。

这一切都工作正常,但我无法弄清楚的是所有变量的去向。

例如,在正常情况下,所有内容都可以在窗口中找到:

var you = "buddy"
alert(window["you"]);
//Alerts : "buddy"

但是当我做一个 eval 时,我不知道"窗口"的等价物是什么。 我不确定所有的变量最终都去了哪里。

我想要的是某种方法来获取所有这些的列表,而没有它们中的任何一个覆盖全局范围内存在的变量。

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");

然后,在全局范围内评估代码,脚本中定义的任何变量都将成为新的全局变量。

你可以在 MDN 上看到这一点的解释。

注意:strict模式下的规则略有不同。

如果你这样做

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

知道了这一点,可以找到更好的解决方案:

下面是一些输入和输出:输入:

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

我正在处理的代码库早已死去,但该代理将捕获所有内容。