为什么eval()存在?

时间:2012-02-01 01:30:35

标签: javascript eval

许多程序员说使用eval()函数是糟糕做法:

When is JavaScript's eval() not evil?

  

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

Is this eval() dangerous?

  

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

Why not eval() JSON?

  

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

Is there ever a good reason to use eval()?

  

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

Why is eval unsafe in javascript?

  

eval的危险只会在你为一个用户bob写的脚本服务于bob浏览器的eval中时显得丑陋...


那为什么它首先存在?

6 个答案:

答案 0 :(得分:9)

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

但是,我同意你在问题中引用的所有内容。使用它的许多原因都是不明智的,最好采用不同的方式 - 但有时,仍然需要,或者它只是其他可用替代品的“最佳选择”。 (由于其他原因,我会专注于Is there ever a good reason to use eval()?的答案。)

+1以获得良好研究的问题。

答案 1 :(得分:8)

eval()存在是因为有时您希望对您的应用程序进行完全编程控制,以便在运行时传入代码。

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

答案 2 :(得分:6)

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

The Eval That Men Do -- A Large-scale Study of the Use of Eval in JavaScript Applications
Mirror on Wayback Machine

迄今为止,对我来说,这是对这个问题最全面的答案。

引自摘要:

  

我们已经记录了337 MB字符串的行为   550,358个调用eval函数的参数在结束时运行   10,000个网站。

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

  1. JSON - JSON字符串或变体。
  2. JSONP - 填充的JSON字符串。
  3. 图书馆 - 一个或多个功能定义。
  4. 读取 - 读取访问权限 对象的属性。
  5. 分配 - 分配给本地变量或 对象属性。
  6. Typeof - 类型测试表达式。
  7. 尝试 - 琐碎 try / catch块。
  8. 调用 - 简单的函数/方法调用。
  9. 空 - 空的或空白的字符串。
  10. 结论的片段(太长而不能引用):

      

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

    一篇值得一读的论文。

答案 3 :(得分:6)

Eval实际上是一个强大的功能,有些东西不可能没有它。例如:

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

    它被认为是“邪恶”的原因是因为新手经常使用这种语言来处理本地语言所能处理的事情。例如,下面的代码:

    age_of_erick = 34;
    age_of_john = 21;
    person = "erick";
    eval("console.log('age_of_"+person+"')");
    

    以下代码:

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

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

答案 4 :(得分:2)

eval()功能就像剪刀一样。你是一个成年人,你有责任不跟他们一起跑。

我已经看到动态语言(如JavaScript)的设计理念被总结为更倾向于让聪明人做一些聪明的事情,以防止愚蠢的人做傻事。 (不幸的是我不记得原始来源或措辞。)

如果您担心使用eval引入错误,可以使用strict mode。它似乎可以防止功能设计的一些问题。 (也就是说,作为一个“神奇”功能,允许破坏你的命名空间。)

答案 5 :(得分:0)

Eval的存在是为了简化JavaScript中的任务。您可以使用它来评估多个语句。而不是必须找到另一种方式,你可以使用eval来做这些事情。尽管不鼓励它具有相当大的力量和用途。