json字符串解析
总结(1.eval 2. new Function 3.$.getJSON)
1.eval
var dataObj=eval("("+data+")");//转换为json对象
e为什么要 eval这里要添加 “("("+data+")");//”呢?
原因在于:eval本身的问题。 由于json是以”{}”的方式来开始以及结束的,在JS中,它会被当
成一个语句块来处理,所以必须强制性的将它转换成一种表达式。
加上圆括号的目的是迫使eval函数在处理JavaScript代码的时候强制将括号内的表达式
(expression)转化为对象,而不是作为语 句(statement)来执行。举一个例子,例如对象字
面量{},如若不加外层的括号,那么eval会将大括号识别为JavaScript代码块的开始 和结束标记
,那么{}将会被认为是执行了一句空语句。所以下面两个执行结果是不同的:
alert(eval("{}"); // return undefined
alert(eval("({})");// return object[Object]
(补充 关于eval中加()的原因)
首先不存在强制运算符这个说法.
这里应该仅是 分组运算符. 作用是优先级. 本质就是舍弃其他可能的多余的语法树.
第5条,之所以要这样做的原因是 {} 花括号二义性造成的.
eval('{a:1}')//不会抛出异常.
eval('{a:1,b:2}')//抛出异常
这并不是eval的错. 错误来自语法分析时, {}被当做 statement block,而不是一个 JSONObject.
所以.抛出异常是因为a:1被解析成lableStatement 了.那么它后面的 "," 逗号,就使得parser不得不停下来了.因为 逗号运算符不能出现在lableStatement后面.
所以
{
a:1,
b:2
}
在任何被解析为statement block的情况下.都将导致异常.
解决办法.把他们并入表达式.让parser使用 JSONObject的语法树.比如
({a:1,b:2})
1,{a:1,b:2}
+{a:1,b:2}
var a ={a:1,b:2}
等等等等...
说说为什么()不是强制运算符,因为它不具备这个功能.
分组运算符 同 delete typeof 等运算符类似. 不会对运算元.造成 GetValue() .
举个例子:
delete 玩笑; //不会抛出异常.
原因是运行时,执行到 delete 玩笑; 时, 并不会对标识符-玩笑,进行GetValue().
delete (玩笑);//同样不会抛出异常.
可见分组运算符() 并没有对 标识符 -玩笑 做额外的工作. 它仅仅是影响语法树的产生过程.
从ECMA262的角度来看此问题亦如此. 这里涉及到 Reference Type 的base property 为null时的情况下,对其 GetValue()才抛出异常.
2.$.getJSON
对于服务器返回的JSON字符串,如果jquery异步请求将type(一般为这个配置属性)设
为“json”,或者利 用$.getJSON()方法获得服务器返回,那么就不需要eval()方法了,因为
这时候得到的结果已经是json对象了,只需直接调用该对象即可,这 里以$.getJSON方法为例说
明数据处理方法:
$.getJSON("http://www.phpzixue.cn/",{param:"gaoyusi"},function(data){
//此处返回的data已经是json对象
//以下其他操作同第一种情况
$.each(data.root,function(idx,item){
if(idx==0){
return true;//同countinue,返回false同break
}
alert("name:"+item.name+",value:"+item.value);
});
});
这里特别需要注意的是方式1中的eval()方法是动态执行其中字符串(可能是js脚本)的,这样很
容易会造成系统的安全问题。所以可以采用一些规避了eval()的第三方客户端脚本库,比如JSON
in JavaScript就提供了一个不超过3k的脚本库。
3.new Function
第二种解析方式就是使用Function对象来完成,它的典型应用就是在JQUERY中的AJAX方法下的
success等对于返回数据data的解析
var json='{"name":"CJ","age":18}';
data =(new Function("","return "+json))();
此时的data就是一个会解析成一个 json对象了
网上有例:
<script type="text/javascript">
//var aa="{aa:'xx'}";
var aa="{name:'cola',item:[{age:11},{age:22},{age:23},{age:23}]}";
var now=new Date().getTime();
for(var i=0;i<1000;i++){
eval("("+aa+")");
}
var now1=new Date().getTime();
alert(now1-now+" eval");
var now2=new Date().getTime();
for(var i=0;i<1000;i++){
var fn=new Function("return"+aa);
fn();
}
var now3=new Date().getTime();
alert(now3-now2+" new Function");
</script>
总结:
在ie下两种方法时间差不多
在ff下,网上提到用ff2下 用new Function比eval快很多,但是自己的ff浏览器为24.0,反而是eval运行的时间更快。。。
(文章参考了:http://jljlpch.iteye.com/blog/240545 以及 http://www.cnblogs.com/fishtreeyu/archive/2011/11/05/2237190.html 多谢分享学习中)