JavaScript中eval的预期用途是什么?

6

1
http://en.wikipedia.org/wiki/Eval#JavaScript - Dan Atkinson
11
它只是拼写错误的 evil()。不要使用它。 - slikts
1
“翻白眼” eval 不一定是邪恶的,这完全取决于你打算用它做什么,有时确实没有其他方法。 - Andy E
https://dev59.com/z3VC5IYBdhLWcg3wvT1a - Andy E
5个回答

9

eval()提供了访问JavaScript编译器的方式,从而允许在以后的某个时间执行代码。传递给函数的参数在经过JavaScript编译器处理后会被执行。

开发人员对eval()的安全性存在争议。它确实不太安全,但如果您绝对确定输入已经过净化处理后再传递,那么这应该不是问题。

eval()的结果通常较慢,因为代码尚未被编译或缓存。使用该函数显然会带来性能损失。

由于最终执行的代码缺乏上下文信息(例如行号),因此使用eval()生成的代码很难进行调试。

在Web开发中,eval()目前最流行的用途之一是反序列化JSON字符串,通常在Ajax应用程序的上下文中使用;但这并不意味着没有其他用途。


我最喜欢这个答案 - 没有废话,只是一个智慧地写成的回答 :) - Andy E

8

eval

对一个 JavaScript 代码字符串求值,而不需要特定的对象。

如果您构造了一个算术表达式作为字符串,您可以使用 eval 在稍后的时间对其进行求值。例如,假设您有一个变量 x。您可以通过将表达式的字符串值(例如“3 * x + 2”)赋给一个变量,并在脚本的稍后位置调用 eval 来推迟涉及 x 的表达式的计算。

使用 eval 时要小心

eval() 是一个危险的函数,它会以调用者的权限执行传递给它的代码。如果您使用可能受到恶意方影响的字符串运行 eval(),则可能会在用户的机器上以您网页/扩展程序的权限运行恶意代码。


“Downvote” 是因为“不要使用 eval”吗? - rahul
我不知道,但是回答上有一个奇怪的踩票。现在似乎已经消失了。 - user181548
我没有给它点踩,但我觉得投票的人可能不喜欢过分强调不使用 eval 的做法。https://dev59.com/z3VC5IYBdhLWcg3wvT1a - Andy E
3
我不喜欢绝对说法,比如“不要使用eval!”。eval是一种工具。当你需要用到它时,就可以使用它,但其他时间不要使用。关键是要学会正确定义“需要”的概念。 - Bryan Oakley
@Bryan:我自己也说不出来得更好了。 - Andy E
显示剩余4条评论

2
您可能希望查看这篇文章,以下是该页面的直接引用,总结了eval的强大之处。

JavaScript EVAL命令在Web应用程序中使用动态内容时非常强大。EVAL可以减少代码量,并简化与加载时未知数据的交互,但需要考虑一些缺点。

这个命令的真正威力在于它能够处理在加载时未知的数据,例如用户输入的数据。正如我所提到的,EVAL接受任何您提供的字符串并执行它,如果适用则返回结果。您可以使用它来执行JavaScript,在加载时不知道要执行什么。例如,如果我们有一个计算脚本,它接受用户提供的方程式并返回结果,您可以使用EVAL执行计算。


这是 eval,不是 EVAL - Tim Down
1
哦,真的吗?这是一句引用。请将您的投诉发送给作者。 - Filip Ekberg
我知道这是一句引用,但你选择在回答中引用它。我相信在这个问题的背景下,没有人会因为大写字母而感到困惑,但这是一种奇怪的方式来呈现一个函数的名称,特别是在一个函数名区分大小写的语言中。 - Tim Down

1

我认为使用它不是那么糟糕,而是危险的。人们说不要使用eval,因为它会打开滥用的漏洞。如果您的输入是安全的,则可以使用它。例如,在Doug Crockford的JSON解析器中,经过正则表达式检查确保没有“危险”的内容后,就会使用它。

人们告诉你不要使用它的另一个原因是,如果您过度使用eval,人们会开始称呼您为Eval Knievel。


0

最近我在尝试为一个新项目想出一种新的约定时,进行了使用eval()命令的实验。

我想要的是这样的:我喜欢有私有公共特权方法的想法,就像Doug Crockford's article中所述,但我希望能够将公共方法/变量暴露在类的顶部,而不是像通常那样放在底部。

考虑一下这个:

var Singleton = function() {
    // Private
    function _one() {
        // code...
    }

    function _two() {
        // code...
    }

    // Public
    return {
        one: _one,
        two: _two
    };
}();

通过三个eval()(其中两个嵌套在主要的eval()中),我能够得到这个语法:

var Singleton = function() {
    // Public
    var $interface = {
        one: $forward,
        two: $forward
    };

    // Private
    function _one() {
        // code...
    }

    function _two() {
        // code...
    }

    // This does the magic
    return eval($init);
}('Singleton');

尽管所有的可能性和常识都在反对,它确实起作用了。(请注意,我还想要一种调试我的命名空间的方法,这就是为什么您可以看到一个字符串传递给单例的原因。$init也处理了这个问题。)

无论如何,我想打字将所有这些内容都是为了表达eval()不一定是JavaScript代码中应该被避免的有病态的可怜儿童,并且可以以比只在(受信任的!)从服务器发送的代码上进行JSON反序列化更多的方式使用。

(虽然在我的情况下,它最终成为了一种脑力锻炼,因为我已经说服自己不必再费心私有方法/变量了,只需使用严格的命名空间约定即可。)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接