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

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

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


当前回答

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

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

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

其他回答

只要可以确定代码的源代码来自您或实际用户,就没有理由不使用eval()。尽管他可以操纵发送到eval()函数的内容,但这并不是一个安全问题,因为他能够操纵网站的源代码,因此可以改变JavaScript代码本身。

所以…何时不使用eval()?Eval()只应该在第三方有可能更改它的情况下才使用。比如拦截客户端和服务器之间的连接(但如果这是一个问题,请使用HTTPS)。你不应该用eval()来解析别人写的代码,比如在论坛上。

底线

如果你创建或净化了你评估的代码,它永远不会是邪恶的。

略为详细

如果在服务器上使用不是由开发人员创建或未经过开发人员处理的客户端提交的输入运行Eval是邪恶的。

如果在客户端上运行Eval,即使使用客户端制作的未经处理的输入,它也不是邪恶的。

显然,您应该始终清理输入,以便对代码使用的内容有一定的控制。

推理

客户端可以运行任何他们想要的代码,即使开发人员没有编写这些代码;这不仅适用于被求值的对象,而且适用于对eval本身的调用。

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

至于客户端脚本,我认为安全性问题是一个有争议的问题。加载到浏览器中的所有内容都受到操作的影响,因此应该这样对待。当有更简单的方法来执行JavaScript代码和/或操作DOM中的对象(例如浏览器中的URL栏)时,使用eval()语句的风险为零。

javascript:alert("hello");

如果有人想操纵他们的DOM,我说swing away。防止任何类型的攻击的安全性应该始终是服务器应用程序的责任。

从实用主义的角度来看,在可以用其他方法完成任务的情况下,使用eval()没有任何好处。但是,在某些特定的情况下应该使用eval。当这样做时,它绝对可以在没有任何破坏页面的风险的情况下完成。

<html>
    <body>
        <textarea id="output"></textarea><br/>
        <input type="text" id="input" />
        <button id="button" onclick="execute()">eval</button>

        <script type="text/javascript">
            var execute = function(){
                var inputEl = document.getElementById('input');
                var toEval = inputEl.value;
                var outputEl = document.getElementById('output');
                var output = "";

                try {
                    output = eval(toEval);
                }
                catch(err){
                    for(var key in err){
                        output += key + ": " + err[key] + "\r\n";
                    }
                }
                outputEl.value = output;
            }
        </script>
    <body>
</html>

Eval()并不坏。或者,如果是的话,它是邪恶的,就像反射、文件/网络I/O、线程和IPC在其他语言中的“邪恶”一样。

如果,出于您的目的,eval()比手动解释更快,或者使您的代码更简单,或更清楚……那么你应该使用它。如果两者都不是,那么你就不应该这么做。就这么简单。