JS编程建议——14:不要滥用eval

建议14:不要滥用eval
eval是一个被滥用得很严重的JavaScript特性。eval函数传递一个字符串给JavaScript编译器,该字符串会被当成一段 JavaScript 程序来解析和执行。
很多开发者对JavaScript语言一知半解,却喜欢使用eval。例如,如果只知道点表示法,却不知道下标表示法,就会按如下方法编写代码:

  1. eval("value = obj." + key + ";");
    而不是按如下方法编写:
  2. value = obj[key];
    使用eval形式的代码会更加难以阅读。这种形式将使代码性能显著降低,因为eval必须运行编译器,同时这种形式减弱了Web应用的安全性,因为它向被求值的文本授予了太多的权限。使用eval与使用with语句一样,降低了语言的性能。

除了显式调用 eval外,JavaScript 还支持隐式调用eval。Function构造器是eval的另一种形式,所以也应该避免使用它。当传递的是字符串参数时,setTimeout和setInterval函数(浏览器提供的函数,能接受字符串参数或函数参数)会像eval那样去处理,因此也应该避免使用字符串参数形式。例如,下面是使用函数参数形式进行的处理。

  1. var obj = {
  2. show1 : function() {
  3. alert(" 时间到!");
  4. },
  5. show2 : function() {
  6. alert("10 秒一次的提醒!");
  7. };
  8. };
  9. setTimeout(obj.show1, 1000);
  10. setTimeout("obj.show1();", 2000);
  11. setInterval(obj.show2, 10000);
  12. 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字符串是否安全的方法,此方法通过两个正则表达式来实现(代码如下)。

  1. var my_JSON_object = !(/[^,:{}[]0-9.-+Eaeflnr-u
    nrt]/.test(text.replace(/"(\.|1)*"/g, ''))) && eval('(' + text + ')');

  1. "\
时间: 2024-08-30 12:02:18

JS编程建议——14:不要滥用eval的相关文章

JS编程建议——3:减少全局变量污染

建议3:减少全局变量污染定义全局变量有3种方式:在任何函数外面直接执行var语句. var f = 'value'; 直接添加一个属性到全局对象上.全局对象是所有全局变量的容器.在Web浏览器中,全局对象名为window. window.f = 'value'; 直接使用未经声明的变量,以这种方式定义的全局变量被称为隐式的全局变量. f = 'value'; 为方便初学者在使用前无须声明变量而有意设计了隐式的全局变量,然而不幸的是忘记声明变量成了一个非常普遍的现象.JavaScript的策略是让

JS编程建议——8:谨慎使用运算符(1)

建议8:谨慎使用运算符(1)1.用===,而不用==JavaScript有两组相等运算符:===和!==.==和!=.===和!==这一组运算符会按照期望的方式工作.如果两个运算数类型一致且拥有相同的值,那么===返回true,而!==返回false.==和!=只有在两个运算数类型一致时才会做出正确的判断,如果两个运算数是不同的类型,会试图强制转换运算数的类型.转换的规则复杂且难以记忆,具体规则如下: '' == '0' // false 0 == '' // true 0 == '0' //

JS编程建议——29:准确使用循环体(1)

建议29:准确使用循环体(1)1.选择正确的循环体在大多数编程语言中,代码执行时间多数消耗在循环的执行上.在一系列编程模式中,循环是最常用的模式之一,因此也是提高性能必须关注的地方之一.理解JavaScript 中循环对性能的影响至关重要,因为死循环或长时间运行的循环会严重影响用户体验.JavaScript定义了4种类型的循环:第一种循环是标准的for循环,与C语言使用同样的语法: for (var i=0; i < 10; i++){ //循环体 } for循环是最常用的循环结构,它由4部分组

JS编程建议——35:获取字节长度

建议35:获取字节长度String对象的length属性能够返回字符串的长度,不管字符是单字节,还是双字节,都作为一个来计算.因此,要获取字符串的字节长度,必须通过手工计算获取,这里介绍两种方法.1)第一种方法是利用循环结构枚举每个字符,并根据字符的字符编码,判断当前字符是单字节还是双字节,然后递加字符串的字节数. String.prototype.lengthB = function( ){ var b = 0, l = this.length; if( l ){ for( var i = 0

JS编程建议——50:正确检测数组类型

建议50:正确检测数组类型由于数组和对象的数据同源性,导致在JavaScript编程中经常会出现:在必须使用数组时使用了对象,或者在必须使用对象时使用了数组.选用数组或对象的规则很简单:当属性名是小而连续的整数时,应该使用数组,或者当对属性的位置和排列顺序有要求时,应该使用数组.否则,使用对象.JavaScript语言对数组和对象的区别是混乱的.typeof运算符检测数组的类型是"object",这没有什么意义,因此在正确检测数组和对象方面JavaScript没有提供很多的机制.这时可

JS编程建议——59:推荐动态调用函数

建议59:推荐动态调用函数调用函数更便捷的方式是使用Function对象的call和apply方法.apply与call方法在本质上没有太大区别,只不过它们传递给函数的参数方式不同, apply是以数组形式进行参数传递,而call方法可以同时传递多个值.如果某个函数仅能够接收多个参数列表,而现在希望把一个数组的所有元素作为参数进行传递,那么使用apply方法就显得非常便利.function max(){ var m = Number.NEGATIVE_INFINITY; // 声明一个负无穷大的

JS编程建议——65:比较函数的惰性求值与非惰性求值

建议65:比较函数的惰性求值与非惰性求值在JavaScript中,使用函数式风格编程时,应该对于表达式有着深刻的理解,并能够主动使用表达式的连续运算来组织代码.1)在运算元中,除了JavaScript默认的数据类型外,函数也作为一个重要的运算元参与运算.2)在运算符中,除了JavaScript的大量预定义运算符外,函数还作为一个重要的运算符进行计算和组织代码.函数作为运算符参与运算,具有非惰性求值特性.非惰性求值行为自然会对整个程序产生一定的负面影响.先看下面这个示例:var a = 2;fun

JS编程建议——74:使用高阶函数

建议74:使用高阶函数高阶函数作为函数式编程众多风格中的一项显著特征,经常被使用.实际上,高阶函数即对函数的进一步抽象.高阶函数至少满足下列条件之一:接受函数作为输入.输出一个函数. 在函数式语言中,函数不但是一种特殊的对象,还是一种类型,因此函数本身是一个可以传来传去的值.也就是说,某个函数在刚开始执行的时候,总可以送入一个函数的参数.传入的参数本身就是一个函数.当然,这个输入的函数相当于某个函数的另外一个函数.当函数执行完毕之后,又可以返回另外一个新的函数,这个返回函数取决于return f

JS编程建议——67:套用函数

建议67:套用函数套用是JavaScript函数一个很有趣的应用.所谓套用就是将函数与传递给它的参数相结合,产生一个新的函数.在函数式编程中,函数本身也是一个值,这种特性允许用户以有趣的方式去操作函数值.例如,在下面代码中定义一个add()函数,该函数能够返回一个新的函数,并把参数值传递给这个新函数,从而实现连加操作.var add = function(n){ return function(m){ return n+m; } }document.writeln(add(2)(3)); //5