我刚刚在GoogleTalks上看到了Nicholas Zakas of Yahoo的视频,谈论加快您的网站速度。他提到的一件事是以相反的顺序进行循环,以跳过两个比较中的一个:for (i = len; i--;) {}
他说要远离for each
的JS库实现。只是为了好玩,我想我会尝试一下。事实证明他错了。
var array1 = new Array();
var array2 = new Array();
var start = 0;
var finished = 0;
start = (new Date).getTime();
$("#newDivTest").children().each(function(i){
array1[i] = $(this).get(0).id;
});
finished = (new Date).getTime() - start;
alert(finished);
start = (new Date).getTime();
var len = $("#newDivTest").children().length;
for (i = len; i--;) {
array2[i] = $(this).get(0).id;
}
finished = (new Date).getTime() - start;
alert(finished);
newDivTest包含1000个空div,其id从“0”开始并上升到“999”。另一个注意事项是$(this).get(0).id
由于某种原因比$(this).attr("id")
快约3倍,有人知道为什么吗?
对于FF3.5,结果为“7”和“45”,IE7给出“30”和“45”,Chrome2给出“4”和“17”,Opera10给出“16”和“16”,以及最后,Safari4给出“4”和“16”。
因此,尼古拉斯最难对付的方法实际上几乎在所有情况下都更快。
我不够聪明,不知道jQuery的each()
- 方法幕后发生了什么,但它必须做正确的事......对吗?
答案 0 :(得分:7)
您的设置中的一个缺陷是您的第二次测试实际上无法正常工作。你写道:
for (i = len; i--;) {
array2[i] = $(this).get(0).id;
}
但是this
没有定义,所以整个操作都会失败。你必须做类似的事情:
var children = $("#newDivTest").children();
for (i = children.length; i--;) {
array2[i] = children.get(i).id;
}
这是一个比性能更紧迫的问题:尽管调用类似jQuery的.each()函数会导致添加函数调用(以及相关的额外开销),但它们也倾向于使表达内容更容易你想要代码。
引用迈克尔·杰克逊:“程序优化的第一条规则:不要这样做。程序优化的第二条规则(仅限专家!):不要这样做。”
答案 1 :(得分:1)
您的测试不是在做不同的事情吗?
在第二次测试中,this
与第一次测试不同。
答案 2 :(得分:1)
稍微偏离主题,而不是直接回答你的主要问题但是,jQuery的每个方法都是这样实现的(jQuery 1.3.2)
jQuery.extend({
/* ... Code taken out for brevity ... */
// args is for internal usage only
each: function( object, callback, args ) {
var name, i = 0, length = object.length;
if ( args ) {
if ( length === undefined ) {
for ( name in object )
if ( callback.apply( object[ name ], args ) === false )
break;
} else
for ( ; i < length; )
if ( callback.apply( object[ i++ ], args ) === false )
break;
// A special, fast, case for the most common use of each
} else {
if ( length === undefined ) {
for ( name in object )
if ( callback.call( object[ name ], name, object[ name ] ) === false )
break;
} else
for ( var value = object[0];
i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
}
return object;
}
/* ... Code taken out for brevity ... */
);
如您所见,callback
函数应用于object
的每个属性。 jQuery对象定义了一个length属性,因此将执行以下循环(通常,不提供args
)
for ( var value = object[0]; i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
在每次迭代中,回调函数会将范围链长度增加1,因此需要更长的时间来解析对象属性的引用。
答案 3 :(得分:1)
我注意到你的问题是“JS循环和填充数组。哪个更快?”,但你的例子实际上是测试各种JQuery选择器的速度,对吧?您可能有兴趣查看:http://mootools.net/slickspeed/
至于“JS循环和填充数组。哪个更快?”,请参见:http://blogs.oracle.com/greimer/resource/loop-test.html