遍历JavaScript中的一组元素的最佳方法是什么?

时间:2020-03-06 14:58:22  来源:igfitidea点击:

在过去以及当前的大多数项目中,我倾向于使用如下所示的for循环:

var elements = document.getElementsByTagName('div');
for (var i=0; i<elements.length; i++) {
    doSomething(elements[i]);
}

我听说使用"反向while"循环更快,但是我没有真正的方法来确认这一点:

var elements = document.getElementsByTagName('div'), 
    length = elements.length;

while(length--) {
    doSomething(elements[length]);
}

在循环遍历JavaScript中的元素或者与此相关的任何数组时,什么是最佳实践?

解决方案

冒着大喊大叫的危险,我会得到一个像jquery或者原型这样的javascript帮助器库,它们将逻辑封装在漂亮的方法中,每个方法都有一个.each方法/迭代器,并且都努力使其与跨浏览器兼容

编辑:此答案发布于2008年。今天,存在更好的构造。这个特殊情况将通过.forEach解决。

我认为使用第一种形式可能是可行的方法,因为它可能是迄今为止已知宇宙中最常见的循环结构,并且由于我不相信反向循环会在现实中节省我们任何时间(仍在进行增量/递减并在每次迭代中进行比较)。

可以被他人识别和阅读的代码绝对是一件好事。

我知道我们不想听,但是:在这种情况下,我认为最佳实践是最易读的。只要环路没有从这里到月球计数,性能增益就不会足够大。

我也建议我们使用简单的方式(KISS!-)

-但是可以找到一些优化,即不要多次测试数组的长度:

var elements = document.getElementsByTagName('div');
for (var i=0, im=elements.length; im>i; i++) {
    doSomething(elements[i]);
}

我更喜欢for循环,因为它更具可读性。从长度到0的循环比从0到长度的循环更有效。如我们所说,使用反向while循环比foor循环更有效。我没有链接到具有比较结果的页面了,但是我记得不同的浏览器之间的差异有所不同。对于某些浏览器,反转的while循环速度是原来的两倍。但是,如果要循环"小"数组,则没有任何区别。在示例中,元素的长度将为"小"

请注意,在某些情况下,我们需要以相反的顺序循环(但是我们可以使用i-too)。

例如,有人想使用新的getElementsByClassName函数在给定类的元素上循环并更改该类。他发现只有两个元素中的一个被更改了(在FF3中)。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
这是因为该函数返回活动的NodeList,从而反映了Dom树中的更改。以相反的顺序遍历列表可以避免此问题。

var menus = document.getElementsByClassName("style2");
for (var i = menus.length - 1; i >= 0; i--)
{
  menus[i].className = "style1";
}

在增加索引级数时,当我们询问索引1时,FF检查Dom并跳过具有style2的第一项,即原始Dom的第二项,因此它返回第三项初始项!

我喜欢这样做:

var menu = document.getElementsByTagName('div');
for (var i = 0; menu[i]; i++) {
     ...
}

每次迭代都没有调用数组的长度。

我们可能还会在我的网站上查看此页面,在这里我比较了递增的" for"循环,反向的" do / while"循环和Duff的Device的速度。

另请参阅我对Andrew Hedges测试的评论...

我只是尝试运行一个测试,以比较一个简单的迭代,我引入的优化和反向do / while,在每个循环中都对数组中的元素进行了测试。

a,不足为奇,虽然经过优化的简单迭代速度最快,但我测试的三种浏览器的结果却大不相同!

测试:

具有50万个元素的数组将在实际测试之外构建,对于每次迭代,都会显示特定数组元素的值。

试运行10次。

IE6:

结果:

简单:984,922,937,984,891,907,906,891,906,906

平均:923.40 ms。

优化:766,766,844,797,750,750,765,765,766,766

平均:773.50毫秒。

反向做/同时:3375,1328,1516,1344,1375,1406,1688,1344,1297,1265

平均:1593.80毫秒。 (注意一个特别尴尬的结果)

Opera 9.52:

结果:

简单:344,343,344,359,343,359,344,359,359,359

平均:351.30 ms。

优化:281,297,297,297,297,281,281,297,281,281,281

平均:289.00 ms

反向做/同时:391,407,391,391,500,407,407,406,406,406

平均:411.20 ms。

FireFox 3.0.1:

结果:

简单:278,251,259,245,243,242,259,246,247,256

平均:252.60毫秒。

优化:267,222,223,226,223,230,221,231,224,230

平均:229.70毫秒。

反向做/同时:414,381,389,383,388,389,381,387,400,379

平均:389.10毫秒。

我认为我们有两种选择。对于诸如jQuery之类的dom元素以及类似的框架,我们可以找到一种很好的迭代方法。第二种方法是for循环。