为什么eval()存在?

use*_*294 32 javascript eval

许多程序员说使用该功能是一种不好的做法eval():

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

我想花一点时间来解决你的问题的前提 - eval()是"邪恶的"......

这个eval()有危险吗?

Buggy evaled代码可能违反安全属性,就像有缺陷的源代码一样容易...

为什么不用eval()JSON?

您的安全性可能有多种方式可能会受到影响......

是否有充分的理由使用eval()?

是的 - 当没有其他方法以合理的清晰度完成给定任务时...这消除了99%使用eval的情况......

为什么eval中的eval不安全?

eval的危险只会在你为一个用户bob写的脚本服务bob的浏览器eval时提供它丑陋的头部...


那为什么它首先存在?

zie*_*mer 10

因为有时候一种需要.例如,eval在JavaScript中使用反射的所有相同原因都可能与使用Java中的反射共享.

但是,我同意你在问题中引用的所有内容.使用它的许多原因都是不明智的,最好采用不同的方式 - 但有时,仍然需要,或者它只是其他可用替代品的"最佳选择".(我会专注于答案是否有充分的理由使用eval()?还有其他原因.)

对你的问题+1进行良好的研究.

  • 为这项优秀的研究快乐地增加了+1.99%的可避免案件属实.1% - 像http://dean.edwards.name/packer/这样的东西 - 在没有它的情况下写它会很疯狂;但是;) (2认同)

sar*_*old 8

eval()存在是因为有时您希望对运行时传入的代码提供对应用程序的完全编程控制.

没有eval()功能的语言肯定可以通过要求每个程序员基本上编写自己 函数来提供(一部分?全部?)这个功能eval()- lex输入,解析输入,根据需要创建新对象,通过简单运行方法或函数字符串比较或类似.本质上,复制已经存在并且调试快速的整个解释器.


ewe*_*nli 6

有一个关于这个主题的研究出版物:

Eval男人们-的使用大规模研究Eval在JavaScript应用程序
上Wayback机器镜像

到目前为止,对我来说这是对这个问题最全面的答案.

从摘要引用:

我们记录了337 MB字符串的行为,作为对超过10,000个网站中执行的eval函数的550,358次调用的参数.

除此之外,他们确定了9类经常性eval:

  1. JSON - JSON字符串或变体.
  2. JSONP - 填充的JSON字符串.
  3. 图书馆 - 一个或多个功能定义.
  4. 读 - 读取对象属性的访问权限.
  5. 分配 - 分配给局部变量或对象属性.
  6. Typeof - 类型测试表达式.
  7. 尝试 - 琐碎的尝试/捕获块.
  8. 调用 - 简单的函数/方法调用.
  9. 空 - 空或空白字符串.

结论的片段(太长而不能引用):

[...]虽然许多用途eval是合法的,但许多用途是不必要的,可以用等效和更安全的代码替换.我们开始这项工作,希望它表明eval可以被其他功能取代.不幸的是,我们的数据不支持这一结论.[...]

一篇论文非常值得一读.


Mai*_*tor 6

Eval实际上是一个强大的功能,如果没有它,有些事情是不可能完成的.例如:

  1. 评估从远程服务器收到的代码.(假设您想通过向其发送JavaScript代码来创建可以远程控制的站点?)
  2. 评估用户编写的代码.如果没有eval,则无法编程,例如,在线编辑器/ REPL.
  3. 动态创建任意长度的函数(function.length是只读的,所以唯一的方法是使用eval).
  4. 加载脚本并返回其值.例如,如果您的脚本是自调用函数,并且您想要对其进行求值并得到它的结果(例如my_result = get_script_result("foo.js"):),那么对函数get_script_result进行编程的唯一方法就是在其中使用eval.
  5. 在不同的闭包中重新创建一个函数.

而你想要做的任何事情都涉及到动态创建代码.

它被认为是"邪恶"的原因是因为新手经常使用它来做本地语言可以处理的事情.例如,下面的代码:

age_of_erick = 34;
age_of_john = 21;
person = "erick";
eval("console.log('age_of_"+person+"')");
Run Code Online (Sandbox Code Playgroud)

以下代码:

age = {erick:34, john:21};
person = "erick";
console.log(age["erick"]);
Run Code Online (Sandbox Code Playgroud)

两者都做同样的事情,除了一个解析一个字符串,从中生成代码,编译成机器代码然后运行,而另一个从哈希中读取一个值,这要快得多.