eval函数是一种强大而简单的动态生成代码的方法,那么有什么注意事项呢?


当前回答

如果你知道你在什么环境中使用它,它并不一定那么糟糕。

如果您的应用程序使用eval()从XMLHttpRequest返回到您自己的站点的某个JSON中创建一个对象,该对象是由受信任的服务器端代码创建的,那么这可能不是问题。

不可信的客户端JavaScript代码无论如何也做不了那么多。只要你执行eval()的对象来自一个合理的源,就没问题。

其他回答

我相信这是因为它可以从字符串执行任何JavaScript函数。使用它可以使人们更容易向应用程序中注入恶意代码。

JavaScript引擎在编译阶段执行了许多性能优化。其中一些可以归结为能够在代码lexx时对其进行静态分析,并预先确定所有变量和函数声明的位置,以便在执行期间解析标识符时花费更少的精力。

但是,如果引擎在代码中发现了eval(..),它本质上必须假设它对标识符位置的所有感知都可能是无效的,因为它在lexlexation时无法确切地知道您可以传递给eval(..)来修改词法作用域的哪些代码,或者您可以传递给对象的内容来创建一个新的词法作用域以供参考。

换句话说,悲观地说,如果eval(..)存在,它所做的大多数优化都是毫无意义的,因此它根本不执行优化。

这就解释了一切。

参考:

https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#eval

https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#performance

这并不总是一个坏主意。以代码生成为例。我最近写了一个叫做Hyperbars的库,它在虚拟世界和把手之间架起了桥梁。它通过解析句柄模板并将其转换为虚拟dom使用的超脚本来实现这一点。超脚本首先作为字符串生成,在返回它之前,eval()将其转换为可执行代码。我发现eval()在这种特殊情况下与邪恶完全相反。

基本上从

<div>
    {{#each names}}
        <span>{{this}}</span>
    {{/each}}
</div>

这个

(function (state) {
    var Runtime = Hyperbars.Runtime;
    var context = state;
    return h('div', {}, [Runtime.each(context['names'], context, function (context, parent, options) {
        return [h('span', {}, [options['@index'], context])]
    })])
}.bind({}))

eval()的性能在这种情况下不是问题,因为您只需要解释一次生成的字符串,然后多次重用可执行输出。

如果您好奇的话,您可以看到代码生成是如何实现的。

这是一篇谈论eval的好文章,以及它如何不是一种邪恶: http://www.nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderstood/

I’m not saying you should go run out and start using eval() everywhere. In fact, there are very few good use cases for running eval() at all. There are definitely concerns with code clarity, debugability, and certainly performance that should not be overlooked. But you shouldn’t be afraid to use it when you have a case where eval() makes sense. Try not using it first, but don’t let anyone scare you into thinking your code is more fragile or less secure when eval() is used appropriately.

通常只有在传递eval用户输入时才会出现问题。