JavaScript 的 eval() 什么时候不是邪恶的?

2022-08-30 00:09:55

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

但是,我总是回避使用如果可以避免它,因为它是邪恶的(而且,无论正确与否,我一直认为它在JavaScript中更加邪恶,因为要评估的代码可能会被用户更改)。eval()

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


答案 1

我想花点时间解决你问题的前提 - eval()是“邪恶的”。编程语言人员使用的“邪恶”一词通常意味着“危险”,或者更准确地说是“能够通过一个简单的命令造成很大的伤害”。那么,什么时候可以使用危险的东西呢?当您知道危险是什么,以及何时采取适当的预防措施时。

关键是,让我们来看看使用eval()的危险。可能有很多小的隐患,就像其他一切一样,但两大风险 - eval()被认为是邪恶的原因 - 是性能和代码注入。

  • 性能 - eval() 运行解释器/编译器。如果你的代码是编译的,那么这是一个很大的打击,因为你需要在运行时的中间调用一个可能很重的编译器。然而,JavaScript仍然主要是一种解释型语言,这意味着在一般情况下调用eval()并不是一个很大的性能打击(但请参阅下面的具体评论)。
  • 代码注入 - eval() 可能在提升的权限下运行一串代码。例如,以管理员/root 身份运行的程序永远不会想要评估()用户输入,因为该输入可能是“rm -rf /etc/important-file”或更糟。同样,浏览器中的JavaScript没有这个问题,因为无论如何,程序都在用户自己的帐户中运行。服务器端JavaScript可能存在这个问题。

关于您的具体情况。据我所知,您是自己生成字符串的,因此假设您小心翼翼地不允许生成像“rm -rf something-important”这样的字符串,则不存在代码注入风险(但请记住,在一般情况下很难确保这一点)。另外,如果你在浏览器中运行,那么代码注入是一个非常小的风险,我相信。

至于性能,您必须将其与编码的易用性进行权衡。我认为,如果您正在解析公式,则最好在解析期间计算结果,而不是运行另一个解析器(eval()内部的解析器)。但是使用eval()进行编码可能更容易,并且性能下降可能不会引起注意。在这种情况下,看起来eval()并不比任何其他可能节省您时间的函数更邪恶。


答案 2

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

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