前些日子用到了eval()处理json数据,习惯于每次添加'('+json+')'处理数据,也没去深究为什么这么做,刚好同事问我这个问题,瞬间哑口无言,只会如何操作,却讲不出原因,这不符合咱程序员严谨的工作态度,仔细思考了一会,简略的谈谈吧。
可能会随时脑洞,望各位见谅。
1.什么是json?
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,是一种取代XML的数据结构,和xml相比,它更小巧但描述能力却不差,由于它的小巧所以网络传输数据将减少更多流量从而加快速度。
- JSON就是一串字符串 只不过元素会使用特定的符号标注,其书写格式是:名称/值对。
{"name":"json"}
- {} 双括号表示对象
- [] 中括号表示数组
- "" 双引号内是属性或值
现在还有很多人存在一些误区,为什么{name:'json'}在检验时通过不了,
那是因为JSON官网最新规范规定
如果是字符串,那不管是键或值最好都用双引号引起来,所以上面的代码就是 {"name":"json"}
不要反驳,官网就是这么定义的。
- : 冒号表示后者是前者的值(这个值可以是字符串、数字、也可以是另一个数组或对象);
2. 如何解析json?
如果从后台接收json数据时,jquery将type设为'json',或者利用$.getJSON()获取,此时接收到的json是对象格式,不需要特殊处理,可直接使用;
但是如果接收的json格式是字符串类型,这时就需要将其转换成对象格式了,两种方法:eval() 和 new Function();
-
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