我正在编写一些JavaScript代码来解析用户输入的函数(用于类似电子表格的功能)。解析完公式后,我可以将其转换为JavaScript并在其上运行eval()以产生结果。

然而,我总是避免使用eval(),因为它是邪恶的(而且,无论正确与否,我一直认为它在JavaScript中更邪恶,因为要计算的代码可能会被用户更改)。

那么,什么时候可以使用它呢?


当前回答

我相信eval对于客户端web应用程序来说是一个非常强大的功能,并且是安全的。和JavaScript一样安全,但JavaScript不安全。:-)安全问题本质上是服务器端的问题,因为现在,使用像Firebug这样的工具,你可以攻击任何JavaScript应用程序。

其他回答

如果真的需要,eval也不是坏事。但是我偶然发现的99.9%的eval使用是不需要的(不包括setTimeout的东西)。

对我来说,邪恶不是性能问题,甚至不是安全问题(好吧,间接地,两者都是)。所有这些不必要的eval使用都增加了维护的难度。重构工具被抛弃了。搜索代码是困难的。这些评估的意想不到的影响是很多的。

当您使用解析函数解析JSON结构时(例如,jQuery.parseJSON),它期望JSON文件的完美结构(每个属性名都用双引号括起来)。然而,JavaScript更加灵活。因此,可以使用eval()来避免它。

在Chrome (v28.0.1500.72)中调试时,我发现如果变量没有在产生闭包的嵌套函数中使用,则它们不会绑定到闭包。我想,这是JavaScript引擎的优化。

但是:当eval()在导致闭包的函数中使用时,外部函数的所有变量都被绑定到闭包中,即使它们根本没有被使用。如果有人有时间测试内存泄漏是否会由此产生,请在下面给我留言。

下面是我的测试代码:

(function () {
    var eval = function (arg) {
    };

    function evalTest() {
        var used = "used";
        var unused = "not used";

        (function () {
            used.toString();   // Variable "unused" is visible in debugger
            eval("1");
        })();
    }

    evalTest();
})();

(function () {
    var eval = function (arg) {
    };

    function evalTest() {
        var used = "used";
        var unused = "not used";

        (function () {
            used.toString();   // Variable "unused" is NOT visible in debugger
            var noval = eval;
            noval("1");
        })();
    }

    evalTest();
})();

(function () {
    var noval = function (arg) {
    };

    function evalTest() {
        var used = "used";
        var unused = "not used";

        (function () {
            used.toString();    // Variable "unused" is NOT visible in debugger
            noval("1");
        })();
    }

    evalTest();
})();

我想在这里指出的是,eval()不一定指向本机eval()函数。这完全取决于函数的名称。因此,当使用别名调用本机eval()时(说var noval = eval;然后在内部函数noval(expression);)中,当表达式引用了应该是闭包的一部分但实际上不是的变量时,表达式的求值可能会失败。

我倾向于遵循Crockford关于eval()的建议,并完全避免使用它。即使是看起来需要它的方法也不需要。例如,setTimeout()允许您传递一个函数而不是eval。

setTimeout(function() {
  alert('hi');
}, 1000);

即使它是一个可信的源,我也不会使用它,因为JSON返回的代码可能是乱码,最好的情况下可能会产生一些不稳定的东西,最坏的情况下可能会暴露一些不好的东西。

让我们看看真正的人:

现在每个主流浏览器都有一个内置的控制台,你想成为黑客的人可以使用它来调用任何值的任何函数-为什么他们会麻烦使用eval语句-即使他们可以? 如果编译2000行JavaScript需要0.2秒,那么如果我计算4行JSON,性能会下降多少?

即使克罗克福德对“eval是邪恶的”的解释也很软弱。

eval是邪恶的,eval函数是最被滥用的功能 JavaScript。避免它

正如克罗克福德自己可能会说的那样:“这种说法往往会产生非理性的神经症。别买它。”

理解eval并知道它什么时候可能有用更重要。例如,eval是评估软件生成的服务器响应的明智工具。

顺便说一句:Prototype.js直接调用eval 5次(包括在evalJSON()和evalResponse()中)。jQuery在parseJSON中使用它(通过函数构造函数)。