你的位置:首页 > Java教程

[Java教程]eval 的使用与延展


前些日子用到了eval()处理json数据,习惯于每次添加'('+json+')'处理数据,也没去深究为什么这么做,刚好同事问我这个问题,瞬间哑口无言,只会如何操作,却讲不出原因,这不符合咱程序员严谨的工作态度,仔细思考了一会,简略的谈谈吧。

可能会随时脑洞,望各位见谅。

  1.什么是json?

  JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,是一种取代

  • JSON就是一串字符串 只不过元素会使用特定的符号标注,其书写格式是:名称/值对。
    {"name":"json"} 

  • {} 双括号表示对象
  • [] 中括号表示数组
  • "" 双引号内是属性或值      

    现在还有很多人存在一些误区,为什么{name:'json'}在检验时通过不了,

  那是因为JSON官网最新规范规定

  如果是字符串,那不管是键或值最好都用双引号引起来,所以上面的代码就是 {"name":"json"}

  不要反驳,官网就是这么定义的。

  • : 冒号表示后者是前者的值(这个值可以是字符串、数字、也可以是另一个数组或对象);  

  2. 如何解析json?

  如果从后台接收json数据时,jquery将type设为'json',或者利用$.getJSON()获取,此时接收到的json是对象格式,不需要特殊处理,可直接使用;

  但是如果接收的json格式是字符串类型,这时就需要将其转换成对象格式了,两种方法:eval() 和 new Function();

  1. eval

  var json='{"name":"lee","age":"15"}'  str=window.eval('('+ json+')');

 

结果如图:

我们可以看出解析后的json数据格式为对象,方便我们的后续操作处理,但是,我们为什么要用'('+json+')'这样的处理呢?

个人拙见如下:首先eval 可将字符串解析为

    • 具体的对象
    • 求表达式的值
    • 执行语句
    • 求值
    • 处理日期数据

还记得json的格式吗?以"{"开头对吧,在此那么你还记的语句块的格式吗?也是以"{"开头是吧,那么问题就来了,eval解析时会把我们的json当成语句块,而且这个所谓的语句块里还有":",那么极有可能会报错,如图:

在此随便扯一点别的知识点。。

表达式与语句

表达式:表达式,是由数字、算符、数字分组符号(括号)、自由变量和约束变量等以能求得数值的有意义排列方法所得的组合。约束变量在表达式中已被指定数值,而自由变量则可以在表达式之外另行指定数值。

语句:JavaScript 语句向浏览器发出的命令。语句的作用是告诉浏览器该做什么。通常我们在每条可执行的语句结尾添加分号以分隔 JavaScript 语句,多条语句构成语句块。

有些时候,表达式和语句会看不出区别,但其作用做不同,即有一些表达式会出现在语句的上下文中,为了解决歧义,JavaScript语法禁止表达式以大括号"{"或关键字"function"开头,如果要以"{"开头的表达式能被正确解析,需要把这个"{}"包裹的内容放在"()"中,确保表达式被解析在表达式上下文中,如果表达式被解析在表达式上下文中,此时json解析后会转换成对象类型,这就是我们想要的结果。

表达式与语句的交集:

            

好了,原理讲解完成,那么各位应该明白以'('+json+')'格式处理eval接收数据的原理了吧,如果实在不明白,那就偷个懒,每次都不加'('+json+')',报错了再加上,时间长了也就能明白了(千万别听我的,我开玩笑的%>_<%)。

但是,but,各位有没有听过前辈们讲过一段话:

对于eval,要理解它,远离它。

为什么呢?

  • 容易受XSS攻击 传送门:http://baike.baidu.com/link?url=FRg1lsOHCUrEjEPp8l2es-TYxk3ZfZR4xNisB_OOvttwL1RyMw0D0M9cuXD78ewFy6exKbP_FMkmIcZgnoP62K
  • 调试不方便
  • 全局变量污染
  • 代码执行更缓慢

为什么执行会缓慢呢? 这就要引出另一位主角了:new  Function();

2.new Function

  先扯些别的,定义函数有三种方式,分别为

  • 函数声明  function fn( arg ) {}
  • 函数表达式 var fn=function( arg ) {};
  • new     var fn=new Function(arg1,arg2...argn,body);   ps:此处的arg参数必须是字符串形式,body为函数体,同样为字符串形式

来看代码:

//1.取最大值var getMax=new Function('Math.max(arguments)');var max=getMax(1,4,5);

//2.处理json数据var json='{"name":"json","age":"18"}';data=(new Function('','return'+json))();console.log(data);

 

 结果如图:  

 

我们再来看看所谓的代码执行缓慢的问题是什么,直接上代码解释:

// 1.eval  function evalFun (){    var start= (new Date).getTime();    var func=eval('(function(a,b,c,d,e,f,g){return a*b*c*d*e*f*g;})');    var result= func(4234,3424,4234,4324,423,34234,53453);    console.log(result);    var time= (new Date).getTime()-start;    return time;  }// 2.new Function  function newFun (){    var start= (new Date).getTime();    var func=new Function(['a','b','c','d','e','f','g'],'return a*b*c*d*e*f*g;');    var result=func(4234,3424,4234,4324,423,34234,53453);    console.log(result);    var time= (new Date).getTime()-start;    return time;}  t1=evalFun();//输出处理时间差,单位ms  t2=newFun();  console.log('时间比(new Function/eval):'+ t2/t1);  //两者时间对比

 

两种方法所处理数据相同,结果相同,请看时间比:

结果清晰明了,差别很大是吧,各位看官,您看懂了吧。

最后:鄙人才疏学浅,在此献丑了,望各位前辈批评指正,在此感谢!------(未完待续)                                      2016-04-05