获得"窗口" eval的对象,并列出所有变量? Javascript eval内联html

时间:2016-02-16 04:46:26

标签: javascript html ajax eval inline

Eval一般不受欢迎,但似乎有必要。

目前,我有一个ajax调用,用于检索具有内联javascript的html文件。然后它通过标记名获取脚本并逐出它。

这一切都运作正常,但我无法弄清楚所有的变种都在哪里。

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

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

但是当我做一个评估时,我不知道等同于什么窗口'是。我不确定所有的变量到底在哪里。

我想要的是获得所有这些列表的一些方法,而不会覆盖全局范围内存在的任何变量。

4 个答案:

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

我正在使用的代码库早已死了,但是该代理可以捕获所有内容。