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


当前回答

不恰当地使用eval会打开你的 注入攻击代码 调试可能更具挑战性 (没有行号等) 经过评估的代码执行速度较慢(没有机会编译/缓存经过评估的代码)

编辑:正如杰夫·沃尔登在评论中指出的那样,第三条在今天已经不像2008年那么正确了。然而,虽然可能会发生一些已编译脚本的缓存,但这将只局限于没有修改地重复计算的脚本。更可能的情况是,您正在计算的脚本每次都经历了轻微的修改,因此无法缓存。我们就说someeval代码执行得更慢。

其他回答

我想到两点:

安全性(但只要您自己生成要计算的字符串,这可能就不是问题) 性能:除非要执行的代码是未知的,否则无法进行优化。(关于javascript和性能,当然是Steve Yegge的演示)

如果您正在执行用户提交的代码,除了可能存在的安全问题之外,大多数情况下,有一种更好的方法,无需在每次执行时都重新解析代码。匿名函数或对象属性可以替代eval的大部分用途,而且更安全、更快。

如果您发现代码中使用了eval(),请记住“eval()是邪恶的”。

这 function接受任意字符串,并将其作为JavaScript代码执行。当代码进入时 问题是事先知道的(不是在运行时确定的),没有理由使用 eval()。 如果代码是在运行时动态生成的,通常有更好的方法 在没有eval()的情况下实现目标。 例如,只用方括号来表示 访问动态属性更好更简单:

// antipattern
var property = "name";
alert(eval("obj." + property));

// preferred
var property = "name";
alert(obj[property]);

使用eval()也有安全隐患,因为您可能正在执行代码(用于 示例来自网络),已被篡改。 这是处理Ajax请求的JSON响应时常见的反模式。 在这些情况下 最好使用浏览器内置的方法来解析JSON响应 当然这是安全有效的。对于不支持原生JSON.parse()的浏览器,可以这样做 使用来自JSON.org的库。

同样重要的是要记住,将字符串传递给setInterval(), setTimeout(), Function()构造函数在很大程度上类似于使用eval(),因此 应该避免。

在幕后,JavaScript仍然需要计算和执行 作为编程代码传递的字符串:

// antipatterns
setTimeout("myFunc()", 1000);
setTimeout("myFunc(1, 2, 3)", 1000);

// preferred
setTimeout(myFunc, 1000);
setTimeout(function () {
myFunc(1, 2, 3);
}, 1000);

使用新的Function()构造函数类似于eval(),应该尝试一下 与护理。它可能是一个强大的结构,但经常被误用。 如果你一定要的话 使用eval(),你可以考虑使用new Function()代替。

这是一个很小的潜力 好处,因为在new Function()中求值的代码将在本地函数中运行 范围,因此在被求值的代码中使用var定义的任何变量都不会变成 自动全局。

防止自动全局变量的另一种方法是将 Eval()调用直接函数。

这并不总是一个坏主意。以代码生成为例。我最近写了一个叫做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.