我正在编写一些 JavaScript 代码来解析用户输入的函数(用于类似电子表格的功能)。解析公式后,我可以将其转换为 JavaScript 并eval()
在其上运行以产生结果。
然而,eval()
如果我能避免它,我总是回避使用它,因为它是邪恶的(不管对错,我一直认为它在 JavaScript 中更加邪恶,因为要评估的代码可能会被用户更改)。
那么,什么时候可以使用呢?
我正在编写一些 JavaScript 代码来解析用户输入的函数(用于类似电子表格的功能)。解析公式后,我可以将其转换为 JavaScript 并eval()
在其上运行以产生结果。
然而,eval()
如果我能避免它,我总是回避使用它,因为它是邪恶的(不管对错,我一直认为它在 JavaScript 中更加邪恶,因为要评估的代码可能会被用户更改)。
那么,什么时候可以使用呢?
我想花一点时间来解决您的问题的前提 - eval() 是“邪恶的”。编程语言人员使用的“邪恶”这个词通常意味着“危险”,或者更准确地说“能够用一个看起来简单的命令造成很多伤害”。那么,什么时候可以使用危险的东西呢?当您知道危险是什么,并采取适当的预防措施时。
说到点子上,让我们来看看使用 eval() 的危险。和其他一切一样,可能存在许多小的隐患,但两大风险——eval() 被认为是邪恶的原因——是性能和代码注入。
关于你的具体情况。据我了解,您是自己生成字符串,因此假设您小心地不允许生成像“rm -rf something-important”这样的字符串,则不存在代码注入风险(但请记住,它非常非常在一般情况下很难确保这一点)。此外,如果您在浏览器中运行,那么代码注入的风险很小,我相信。
至于性能,您必须权衡编码的难易程度。我的观点是,如果您正在解析公式,您最好在解析期间计算结果,而不是运行另一个解析器(eval() 中的那个)。但是使用 eval() 编码可能更容易,并且性能下降可能不会引起注意。在这种情况下,看起来 eval() 并不比任何其他可能为您节省一些时间的函数更邪恶。
eval()
不邪恶。或者,如果是的话,它就像反射、文件/网络 I/O、线程和 IPC 在其他语言中是“邪恶的”一样邪恶。
如果,为了您的目的,eval()
比手动解释更快,或者使您的代码更简单或更清晰……那么您应该使用它。如果两者都不是,那么你不应该。就那么简单。
当您信任来源时。
在 JSON 的情况下,或多或少难以篡改源,因为它来自您控制的 Web 服务器。只要 JSON 本身不包含用户上传的数据,使用 eval 就没有大的缺点。
在所有其他情况下,我会竭尽全力确保用户提供的数据在将其提供给 eval() 之前符合我的规则。
让我们来看看真正的人:
现在每个主要浏览器都有一个内置控制台,您的潜在黑客可以大量使用它来调用具有任何值的任何函数 - 他们为什么要费心使用 eval 语句 - 即使他们可以?
如果编译 2000 行 JavaScript 需要 0.2 秒,那么如果我对四行 JSON 求值,我的性能下降是什么?
甚至 Crockford 对“eval 是邪恶的”的解释也很薄弱。
eval is Evil,eval 函数是 JavaScript 中最容易被误用的特性。躲开它
正如克罗克福德本人可能会说的那样“这种说法往往会产生非理性的神经症。不要买它。”
理解 eval 并知道它何时可能有用更重要。例如, eval 是用于评估由您的软件生成的服务器响应的明智工具。
顺便说一句:Prototype.js 直接调用 eval 5 次(包括在 evalJSON() 和 evalResponse() 中)。jQuery 在 parseJSON 中使用它(通过 Function 构造函数)。
我倾向于遵循克罗克福德的意见为eval()
,并完全避免。即使看起来需要它的方法也不需要。例如,setTimeout()
允许您传递函数而不是 eval。
setTimeout(function() {
alert('hi');
}, 1000);
即使它是可信来源,我也不使用它,因为 JSON 返回的代码可能是乱码,这充其量可能会做一些不稳定的事情,最坏的情况是暴露一些不好的东西。