当前位置: 首页 > 图文教程 > 网络编程 > Javascript > JavaScript 解析Json字符串的性能比较分析代码

Javascript
JavaScript 序列化对象实现代码
替代window.event.srcElement效果的可兼容性的函数
div+css+js模拟tab切换效果 事件绑定 IE,firefox兼容
IE和Firefox下event事件杂谈
javascript option onclick事件ie解决方案 兼容ie,firefox
javascript demo 基本技巧
用js实现层随着内容大小动态渐变改变 推荐
JS 的应用开发初探(mootools)
JS 在数组插入字符的实现代码(可参考JavaScript splice() 方法)
JQuery Tips(4) 一些关于提高JQuery性能的Tips
jQuery 淡入淡出、展开收缩菜单实现代码
js控制div及网页相关属性的代码
javascript 翻页测试页(动态创建标签并自动翻页)
Js获取table当前tr行的值的代码
IE 上下滚动展示模仿Marquee机制
jQuery解决iframe高度自适应代码
jQuery 连续列表实现代码
利用jQuery的$.event.fix函数统一浏览器event事件处理
Javascript和Ajax中文乱码吐血版解决方案
js Firefox 加入收藏夹功能代码 兼容Firefox 和 IE

Javascript 中的 JavaScript 解析Json字符串的性能比较分析代码


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2010-01-10   浏览: 49 ::
收藏到网摘: n/a

我们在使用AJAX来做服务器端和客户端交互的时候,一般的做法是让服务器端返回一段JSON字符串,然后在客户端把它解析成JavaScript对象。 解析时用到的方法一般是eval或者new function,而目前IE8和Firefox3.1又内置了原生的JSON对象(据说会有一定的性能提升)。那我们在实际使用的时候怎样从这三种方法(因为性能问题,不考虑用javascript实现的解析)里面来选择呢?面对众多的浏览器,哪种方式的性能是最好的呢?
一、测试方法

1、首先指定测试次数及JSON字符串
复制代码 代码如下:

var count = 10000, o = null, i = 0, jsonString = '{"value":{"items": [{"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}]},"error":null}';

2、循环解析并记录时间
eval
复制代码 代码如下:

var beginTime = new Date();
for ( i = 0; i < count; i++ ) {
o = eval( "(" + jsonString + ")" );
}
Console.output( "eval:" + ( new Date() - beginTime ) );

new Function
复制代码 代码如下:

var beginTime = new Date();
for ( i = 0; i < count; i++ ) {
o = new Function( "return " + jsonString )();
}
Console.output( "new Function:" + ( new Date() - beginTime ) );

native
复制代码 代码如下:

if ( typeof JSON !== "undefined" ) {
var beginTime = new Date();
for ( i = 0; i < count; i++ ) {
o = JSON.parse( jsonString ); }
Console.output( "native:" + ( new Date() - beginTime ) );
} else {
Console.output( "native:not support!" );
}

二、测试对象

选择目前主流的浏览器(不考虑Maxthon一类的外壳),包括IE6、7、8,Firefox2、3、3.1,Chrome,Opera及Safari3、4。
三、测试环境
T9300 CPU + 4G RAM + Windows2003,其中IE8使用的是Vista的环境,IE7在另外一台工作机(2G CPU + 2G RAM + Windows2003),考虑到主要是测试浏览器客户端的性能,结果的误差应该能够接受。
四、测试结果
image
*数值越小越好
*在当前列中绿色背景的表示性能最好,红色性能最差
1、Firefox2、3全部垫底,IE6的性能优于IE7(可能和机器不一致有关),Chrome和Safari4的性能远远超出其它浏览器。
2、不同的浏览器下eval和new Function的性能不一致,总的来说eval更好,但Firefox下new Function的性能是eval的一倍,为了更好的兼容各个浏览器,我们把对JSON的解析单独封装成一个对象来处理:
wrapper
复制代码 代码如下:

var __json = null;
if ( typeof JSON !== "undefined" ) {
__json = JSON;
}
var browser = Browser;
var JSON = {
parse: function( text ) {
if ( __json !== null ) {
return __json.parse( text );
}
if ( browser.gecko ) {
return new Function( "return " + text )();
}
return eval( "(" + text + ")" )
}
};
var beginTime = new Date();
for ( i = 0; i < count; i++ ) {
o = JSON.parse( jsonString ); }
Console.output( "wrapper:" + ( new Date() - beginTime ) );

加入Wrapper后的结果:
image
由于涉及到调用对象的开销,封装后JSON对象会比单独调用更慢,但它能保证在各个浏览器下使用最适合的方法。

五、结论
解析Json字符串时,不同的浏览器选择不同的方法:
IE6、7使用eval
IE8使用原生的JSON对象
Firefox2、3使用new Function
Safari4使用eval
其它浏览器下eval和new Function的性能基本一致
如果有不同意见欢迎拍砖:)
Update:
2009.03.23:屏蔽所有Firefox的Add-Ons再进行测试
由于Known在Firefox下运行代码得到了完全不一致的结果,怀疑是Firefox的插件导致,于是禁掉所有插件后(后来表明几乎由Firebug导致),重新在Firefox2、3下测试了一下,结果如下:
image
这表明Firefox本身的性能并不是象我们先前测试的那样低,在去掉插件后性能还是很不错。但是没有Firebug一类的插件支持,Firefox对我们的吸引力也大大降低了。
2009.03.31:循环中每次使用新的json字符串
根据Oliver的描述,他猜测是由于Safari4和Chrome缓存了eval的结果从而导致它们的测试成绩“虚”高,测试结果证明了他的推测:
image
从这个结果中我们可以看到,Opera的性能最好,Ie8其次。
主要修改的代码:
复制代码 代码如下:

//eval 2: var beginTime = new Date();
for ( i = 0; i < count; i++ ) {
o = eval("(" + '{"value":{"items": [{"x":' + i + ',"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}]},"error":null}' + ")");
}
Console.output( "eval:" + ( new Date() - beginTime ) );
//new Function
beginTime = new Date();
for ( i = 0; i < count; i++ ) {
o = new Function("return " + '{"value":{"items": [{"x":' + i + ',"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}]},"error":null}')();
}
Console.output( "new Function:" + ( new Date() - beginTime ) );
//native
if ( typeof JSON !== "undefined" ) {
beginTime = new Date();
for ( i = 0; i < count; i++ ) {
o = JSON.parse('{"value":{"items": [{"x":' + i + ',"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}]},"error":null}');
}
Console.output( "native:" + ( new Date() - beginTime ) );
} else {
Console.output( "native:not support!" );
}
//wrapper
var __json = null;
if ( typeof JSON !== "undefined" ) {
__json = JSON;
}
var browser = Browser;
var JSON = {
parse: function( text ) {
if ( __json !== null ) {
return __json.parse( text );
}
if ( browser.gecko ) {
return new Function( "return " + text )();
}
return eval( "(" + text + ")" )
}
};
beginTime = new Date();
for ( i = 0; i < count; i++ ) {
o = JSON.parse('{"value":{"items": [{"x":' + i + ',"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}]},"error":null}');
}
Console.output( "wrapper:" + ( new Date() - beginTime ) );

附:全部代码
复制代码 代码如下:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Parse JsonString</title>
</head>
<body>
<div id="consoleRegion"></div>
<script type="text/javascript">
//yui
var Browser = function() {
var o = {
ie: 0,
opera: 0,
gecko: 0,
webkit: 0
};
var ua = navigator.userAgent, m;
if ( ( /KHTML/ ).test( ua ) ) {
o.webkit = 1;
}
// Modern WebKit browsers are at least X-Grade
m = ua.match(/AppleWebKit\/([^\s]*)/);
if (m&&m[1]) {
o.webkit=parseFloat(m[1]);
}
if (!o.webkit) { // not webkit
// @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr)
m=ua.match(/Opera[\s\/]([^\s]*)/);
if (m&&m[1]) {
o.opera=parseFloat(m[1]);
} else { // not opera or webkit
m=ua.match(/MSIE\s([^;]*)/);
if (m&&m[1]) {
o.ie=parseFloat(m[1]);
} else { // not opera, webkit, or ie
m=ua.match(/Gecko\/([^\s]*)/);
if (m) {
o.gecko=1; // Gecko detected, look for revision
m=ua.match(/rv:([^\s\)]*)/);
if (m&&m[1]) {
o.gecko=parseFloat(m[1]);
}
}
}
}
}
return o;
}();
var Console = {
consoleRegion: null,
getRegion: function() {
if ( this.consoleRegion === null ) {
this.consoleRegion = document.getElementById( "consoleRegion" );
}
return this.consoleRegion;
},
output: function( text ) {
this.getRegion().innerHTML += "<br/>" + text;
}
};
//test code
var count = 10000, o = null, i = 0, jsonString = '{"value":{"items": [{"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}, {"x":1,"y":2,"z":3}]},"error":null}';
//eval
var beginTime = new Date();
for ( i = 0; i < count; i++ ) {
o = eval( "(" + jsonString + ")" );
}
Console.output( "eval:" + ( new Date() - beginTime ) );
//new Function
beginTime = new Date();
for ( i = 0; i < count; i++ ) {
o = new Function( "return " + jsonString )();
}
Console.output( "new Function:" + ( new Date() - beginTime ) );
//native
if ( typeof JSON !== "undefined" ) {
beginTime = new Date();
for ( i = 0; i < count; i++ ) {
o = JSON.parse( jsonString );
}
Console.output( "native:" + ( new Date() - beginTime ) );
} else {
Console.output( "native:not support!" );
}
//wrapper
var __json = null;
if ( typeof JSON !== "undefined" ) {
__json = JSON;
}
var browser = Browser;
var JSON = {
parse: function( text ) {
if ( __json !== null ) {
return __json.parse( text );
}
if ( browser.gecko ) {
return new Function( "return " + text )();
}
return eval( "(" + text + ")" )
}
};
beginTime = new Date();
for ( i = 0; i < count; i++ ) {
o = JSON.parse( jsonString );
}
Console.output( "wrapper:" + ( new Date() - beginTime ) );
//alert( o.value.items[0].z );
</script>
</body>
</html>