javascript循环性能大比拼
- 时间:2015年04月02日 15:49:34 来源:魔法猪系统重装大师官网 人气:2063
在设计选择器,我就做了这方面的比较,只不过这次幸运遇到另一个测试程序,它覆盖面更广,测试类型更全面。最后发现自己在选择器中用了一个很慢的循环……囧。由于IE性能比较低下,原程序根本无法运行,因此我把它移到我的博客上来,汉化一下,并减少大量的测试个数(原程序测试个数为1000,我把IE的测试个数减少为300)。但即使这样,它还是弹出警告框问你是否中止循环,你继续按否,就能看到结果了。 查看运行实例:http://www.cnblogs.com/rubylouvre/archive/2010/01/29/1658824.html
var chars = '0123456789abcdef';
function getRandomString() {
var len = Math.ceil(Math.random() * 7) + 3; // 4-10
var result = "";
while (len--) {
result += chars.charAt(Math.floor(Math.random() * chars.length));
}
return result;
}
function createDummySpans(howMany) {
for (var i=0; i
span.innerHTML = ' ' + getRandomString() + ' ';
document.body.appendChild(span);
}
}
function esc(str) {
str=str.replace(/&/g,'&').replace(//g,'>');
return str;
}
var forEachImp = 'native';
if (!Array.prototype.forEach) {
forEachImp = 'custom';
Array.prototype.forEach = function(fun) {
var len = this.length;
if (typeof fun != "function") { throw new TypeError(); }
var thisp = arguments[1];
for (var i = 0; i < len; i++) {
if (i in this) { fun.call(thisp, this[i], i, this); }
}
};
}
function test() {
document.getElementById('h').firstChild.data = 'Testing...';
document.getElementById('h').style.color='#c60';
var size = !+"\v1" ? 300 : 1000;
var mult = 100;
var arr = [];
var lsize = size;
while (lsize--) { arr.push('' + getRandomString() + ''); }
var sarr = [];
var lsize = size;
var which_i = 0;
while (lsize--) {
var skip_ahead = 0;
if (Math.random()> 0.4) {
skip_ahead = Math.ceil(Math.random() * 10);
} else if (Math.random()> 0.2) {
skip_ahead = Math.ceil(Math.random() * 50);
}
which_i += skip_ahead;
sarr[which_i] = '' + getRandomString() + '';
}
createDummySpans(size);
var hColl = document.getElementsByTagName('span');
var start = {};
var end = {};
var comment = {};
var testDesc;
var result = "";
//#########################################
testDesc = "for (var i=0; i
for(var a=0;a
end[testDesc] = new Date().getTime();
comment[testDesc] = '普通for循环';
//#########################################
testDesc = "for (var i=0, len=arr.length; i
for(var a=0;a
end[testDesc] = new Date().getTime();
comment[testDesc] = 'for循环,但预先缓存length属性';
//#########################################
testDesc = "var i = 0; while (i < arr.length) { i++; }";
start[testDesc] = new Date().getTime();
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = '普通while循环';
//#########################################
testDesc = "var i = 0, len = arr.length; while (i < len) { i++; }";
start[testDesc] = new Date().getTime();
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = 'while循环,但预先缓存length属性';
//#########################################
testDesc = "var i = arr.length; while (i--) { }";
start[testDesc] = new Date().getTime();
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = '倒序while循环';
//#########################################
testDesc = "var i = arr.length-1; do { } while (i--);";
start[testDesc] = new Date().getTime();
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = 'do ... while循环';
//#########################################
testDesc = "for (var i=arr.length; i--;) { }";
start[testDesc] = new Date().getTime();
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = '倒序for循环';
//#########################################
var popArrs = [];
for (var i=0; i
start[testDesc] = new Date().getTime();
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = '通过pop方法驱动while循环(但可能会在稀疏数组中出错).';
//#########################################
testDesc = "for (var i in arr) { }";
start[testDesc] = new Date().getTime();
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = 'for...in循环(但可能会遍历更多东西)';
//#########################################
testDesc = "var isInt = /(^[0-9]$)|(^[1-9][0-9]+$)/; for (var i in arr) { if(!isInt.test(i)){continue;} }";
start[testDesc] = new Date().getTime();
var isInt = /(^[0-9]$)|(^[1-9][0-9]+$)/;
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = 'for...in循环并进行isInt检测';
//#########################################
testDesc = "for (var i=0; arr[i]; i++) { }";
start[testDesc] = new Date().getTime();
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = 'for循环,利用元素的自动转换进行中断循环(但如果某个元素为零……).';
//#########################################
testDesc = "for (var i=0; arr[i]; i++) { var x = arr[i]; }";
start[testDesc] = new Date().getTime();
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = '同上,并增加更多检测';
//#########################################
testDesc = "for (var i=0, x; x = arr[i++];) { }";
start[testDesc] = new Date().getTime();
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = '同上,合并当中两个步骤.';
//#########################################
testDesc = "for (var i=0, len=arr.length; < len; i++) { var x = arr[i]; }";
start[testDesc] = new Date().getTime();
for(var a=0;a
end[testDesc] = new Date().getTime();
comment[testDesc] = '普通循环,并在循环增加引用';
//#########################################
testDesc = "arr.forEach(function(x){});";
start[testDesc] = new Date().getTime();
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = forEachImp+' forEach循环';
//#########################################
testDesc = "var f=function(x){}; for (var i=0, len=arr.length; i
for(var a=0;a
end[testDesc] = new Date().getTime();
comment[testDesc] = '用for循环模拟forEach';
//#########################################
result += '
'+comment[testDesc]+' | ';'+esc(testDesc)+' | ';'+(end[testDesc] - start[testDesc])+'ms | ';
var start = {};
var end = {};
var comment = {};
//#########################################
testDesc = "for (var i=0; i
for(var a=0;a
end[testDesc] = new Date().getTime();
comment[testDesc] = '普通for循环';
//#########################################
testDesc = "for (var i=0, len=sarr.length; i
for(var a=0;a
end[testDesc] = new Date().getTime();
comment[testDesc] = 'for循环,但预先缓存length属性';
//#########################################
testDesc = "var i = 0; while (i < sarr.length) { i++; }";
start[testDesc] = new Date().getTime();
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = '普通while循环';
//#########################################
testDesc = "var i = 0, len = sarr.length; while (i < len) { i++; }";
start[testDesc] = new Date().getTime();
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = 'while循环,但预先缓存length属性';
//#########################################
testDesc = "var i = sarr.length; while (i--) { }";
start[testDesc] = new Date().getTime();
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = '倒序while循环';
//#########################################
testDesc = "var i = sarr.length-1; do { } while (i--);";
start[testDesc] = new Date().getTime();
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = 'do ... while循环';
//#########################################
testDesc = "for (var i=sarr.length; i--;) { }";
start[testDesc] = new Date().getTime();
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = '倒序for循环';
//#########################################
testDesc = "for (var i in sarr) { }";
start[testDesc] = new Date().getTime();
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = 'for...in循环';
//#########################################
testDesc = "var isInt = /(^[0-9]$)|(^[1-9][0-9]+$)/; for (var i in sarr) { if(!isInt.test(i)){continue;} }";
start[testDesc] = new Date().getTime();
var isInt = /(^[0-9]$)|(^[1-9][0-9]+$)/;
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = 'for...in循环并进行isInt检测';
//#########################################
testDesc = "sarr.forEach(function(x){});";
start[testDesc] = new Date().getTime();
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] =forEachImp+ 'Array.forEach() ';
//#########################################
testDesc = "var f=function(x){}; for (var i=0, len=sarr.length; i
for(var a=0;a
end[testDesc] = new Date().getTime();
comment[testDesc] = '用for循环模拟forEach';
//#########################################
result += '
'+comment[testDesc]+' | ';'+esc(testDesc)+' | ';'+(end[testDesc] - start[testDesc])+'ms | ';
var start = {};
var end = {};
var comment = {};
//#########################################
testDesc = "for (var i=0; i
for(var a=0;a
end[testDesc] = new Date().getTime();
comment[testDesc] = '普通for循环';
//#########################################
testDesc = "for (var i=0, len=hColl.length; i
for(var a=0;a
end[testDesc] = new Date().getTime();
comment[testDesc] = 'for循环,但预先缓存length属性';
//#########################################
testDesc = "var i = 0; while (i < hColl.length) { i++; }";
start[testDesc] = new Date().getTime();
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = '普通while循环';
//#########################################
testDesc = "var i = 0, len = hColl.length; while (i < len) { i++; }";
start[testDesc] = new Date().getTime();
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = 'while循环,但预先缓存length属性';
//#########################################
testDesc = "var i = hColl.length; while (i--) { }";
start[testDesc] = new Date().getTime();
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = '倒序while循环';
//#########################################
testDesc = "var i = hColl.length-1; do { } while (i--);";
start[testDesc] = new Date().getTime();
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = 'do ... while循环';
//#########################################
testDesc = "for (var i=hColl.length; i--;) { }";
start[testDesc] = new Date().getTime();
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = '倒序for循环';
//#########################################
testDesc = "for (var i in hColl) { }";
start[testDesc] = new Date().getTime();
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = 'for...in循环';
//#########################################
testDesc = "var isInt = /(^[0-9]$)|(^[1-9][0-9]+$)/; for (var i in hColl) { if(!isInt.test(i)){continue;} }";
start[testDesc] = new Date().getTime();
var isInt = /(^[0-9]$)|(^[1-9][0-9]+$)/;
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = 'for...in循环并进行isInt检测';
//#########################################
testDesc = "for (var i=0; hColl[i]; i++) { }";
start[testDesc] = new Date().getTime();
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = 'for循环,通过自动转换元素来中断循环';
//#########################################
testDesc = "for (var i=0; hColl[i]; i++) { var x = hColl[i]; }";
start[testDesc] = new Date().getTime();
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = '同上,并在循环中引用元素';
//#########################################
testDesc = "for (var i=0, x; x = hColl[i++];) { }";
start[testDesc] = new Date().getTime();
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = '同上,不过是利用引用中断循环';
//#########################################
testDesc = "for (var i=0, x; x = hColl.item(i++);) { }";
start[testDesc] = new Date().getTime();
for(var a=0;a
}
end[testDesc] = new Date().getTime();
comment[testDesc] = '同上,不过是通过item获取元素然后放到变量';
//#########################################
testDesc = "for (var i=0, len=hColl.length; i
for(var a=0;a
end[testDesc] = new Date().getTime();
comment[testDesc] = 'for循环,在循环增加引用元素';
//#########################################
result += '
'+comment[testDesc]+' | ';'+esc(testDesc)+' | ';'+(end[testDesc] - start[testDesc])+'ms | ';
document.body.innerHTML += result;
document.getElementById('h').firstChild.data = 'Done Testing.';
document.getElementById('h').style.color='#060';
}
javascript循环测试程序
开始测试
运行代码
由上面的实验我们基本上可得出以下结论:
while循环比for循环快。
倒序循环比顺序循环快。
缓存length属性比不缓存快。
请不要用arr[i]来判断是否中止循环。
请不要在循环内声明变量,用它来引用数组元素,若真的想省几个字符,请在循环外声明。
除非是循环对象的属性,请不要用for...in循环。
请不要用JavaScript 1.6 的forEach迭代器,特慢!
由于javascript与DOM紧密相连,操作DOM基本上是操作其中的元素节点,因此我觉得基本上以下几个循环就够用:
01.//顺序
02.for(var i=0,n=arr.length;i
04.var i = 0, n= arr.length; while (i
06.//倒序
07.
08.var i = arr.length; while (i--) { }
09.
10.//遍历对象(不要用在数组上)
11.var val;
12.for(var key in obj){
13.
val = obj[key]
14.}