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

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

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


当前回答

Eval很少是正确的选择。虽然在许多情况下,您可以通过将脚本连接在一起并动态运行来完成需要完成的任务,但您通常可以使用更强大和可维护的技术:关联数组符号(obj["prop"]与obj.prop相同)、闭包、面向对象技术、函数技术—请使用它们。

其他回答

如果你可以完全控制传递给eval函数的代码,那么使用它是可以的。

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

代码生成。我最近写了一个叫做Hyperbars的库,它在虚拟世界和把手之间架起了桥梁。它通过解析句柄模板并将其转换为超脚本来实现这一点。超脚本首先作为字符串生成,在返回它之前,eval()将其转换为可执行代码。我发现eval()在这种特殊情况下与邪恶完全相反。

基本上从

<div>
    {{#each names}}
        <span>{{this}}</span>
    {{/each}}
</div>

这个

(function (state) {
    var Runtime = Hyperbars.Runtime;
    var context = state;
    return h('div', {}, [Runtime.each(context['names'], context, function (context, parent, options) {
        return [h('span', {}, [options['@index'], context])]
    })])
}.bind({}))

eval()的性能在这种情况下也不是问题,因为您只需要解释一次生成的字符串,然后多次重用可执行输出。

如果您好奇的话,您可以看到代码生成是如何实现的。

我看到有人提倡不要使用eval,因为这是邪恶的,但我也看到同样的人动态地使用Function和setTimeout,所以他们在幕后使用eval:D

顺便说一句,如果你的沙盒不够确定(例如,如果你在一个允许代码注入的网站上工作),eval是你的最后一个问题。安全的基本规则是所有输入都是邪恶的,但对于JavaScript,甚至JavaScript本身也可能是邪恶的,因为在JavaScript中,你可以覆盖任何函数,你只是不能确定你使用的是真正的函数,所以,如果恶意代码在你之前启动,你不能相信任何JavaScript内置函数:D

现在这篇文章的尾声是:

如果你真的需要它(80%的时间不需要eval),并且你确定你在做什么,只使用eval(或更好的Function;)),闭包和OOP覆盖了80/90%的情况,其中eval可以使用另一种逻辑替换,其余是动态生成的代码(例如,如果你正在编写解释器),正如你已经说过的评估JSON(这里你可以使用Crockford安全评估;))

当没有宏时,Eval对于代码生成很有用。

举个愚蠢的例子,如果你正在编写一个Brainfuck编译器,你可能想要构造一个函数,它以字符串的形式执行指令序列,并对它进行eval以返回一个函数。