建议14:不要滥用eval
eval是一个被滥用得很严重的JavaScript特性。eval函数传递一个字符串给JavaScript编译器,该字符串会被当成一段 JavaScript 程序来解析和执行。
很多开发者对JavaScript语言一知半解,却喜欢使用eval。例如,如果只知道点表示法,却不知道下标表示法,就会按如下方法编写代码:
- eval("value = obj." + key + ";");
而不是按如下方法编写: - value = obj[key];
使用eval形式的代码会更加难以阅读。这种形式将使代码性能显著降低,因为eval必须运行编译器,同时这种形式减弱了Web应用的安全性,因为它向被求值的文本授予了太多的权限。使用eval与使用with语句一样,降低了语言的性能。
除了显式调用 eval外,JavaScript 还支持隐式调用eval。Function构造器是eval的另一种形式,所以也应该避免使用它。当传递的是字符串参数时,setTimeout和setInterval函数(浏览器提供的函数,能接受字符串参数或函数参数)会像eval那样去处理,因此也应该避免使用字符串参数形式。例如,下面是使用函数参数形式进行的处理。
- var obj = {
- show1 : function() {
- alert(" 时间到!");
- },
- show2 : function() {
- alert("10 秒一次的提醒!");
- };
- };
- setTimeout(obj.show1, 1000);
- setTimeout("obj.show1();", 2000);
- setInterval(obj.show2, 10000);
- setInterval("obj.show2();", 10000);
在Ajax应用中,JSON是一种流行的浏览器端与服务器端之间传输数据的格式。服务器端传过来的数据在浏览器端通过JavaScript的eval方法转换成可以直接使用的对象。然而,在浏览器端执行任意的 JavaScript会带来潜在的安全风险,恶意的JavaScript代码可能会破坏应用。对于这个问题,有两种解决方法:
带注释的 JSON(JSON comments filtering)。
带前缀的 JSON(JSON prefixing)。
这两种方法都是在Dojo中用来避免JSON劫持(JSON hijacking)的方法。带注释的JSON指的是从服务器端返回的JSON数据都是带有注释的,浏览器端的JavaScript代码需要先去掉注释的标记,再通过eval 来获得JSON数据。这种方法一度被广泛使用,后来被证明并不安全,还会引入其他的安全漏洞。带前缀的JSON是目前推荐使用的方法,这种方法的使用非常简单,只需要在从服务器端返回的JSON字符串之前加上{} &&,再调用eval方法。关于这两种方法的细节,可参考http://www.ibm.com/developerworks/cn/web/wa-lo-dojoajax1/?S_TACT=105AGX52&S_CMP=tec-csdn#resources中的内容。对JSON字符串进行语法检查,安全的JSON应该是不包含赋值和方法调用的。在JSON的RFC 4627中,给出了判断JSON字符串是否安全的方法,此方法通过两个正则表达式来实现(代码如下)。
- var my_JSON_object = !(/[^,:{}[]0-9.-+Eaeflnr-u
nrt]/.test(text.replace(/"(\.|1)*"/g, ''))) && eval('(' + text + ')');
- "\