eval函数是一种强大而简单的动态生成代码的方法,那么有什么注意事项呢?
当前回答
我相信这是因为它可以从字符串执行任何JavaScript函数。使用它可以使人们更容易向应用程序中注入恶意代码。
其他回答
如果您发现代码中使用了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()调用直接函数。
我相信这是因为它可以从字符串执行任何JavaScript函数。使用它可以使人们更容易向应用程序中注入恶意代码。
这是一篇谈论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.
这并不总是一个坏主意。以代码生成为例。我最近写了一个叫做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()成为动态内容(通过cgi或输入),否则它就像页面中所有其他JavaScript一样安全可靠。