在过去,大多数我目前的项目,我倾向于使用像这样循环:
var elements = document.getElementsByTagName('div');
for (var i=0; i<elements.length; i++) {
doSomething(elements[i]);
}
我听说使用循环更快,但我有没有真正的方法来证实这一点“而反向”:
var elements = document.getElementsByTagName('div'),
length = elements.length;
while(length--) {
doSomething(elements[length]);
}
什么被认为是最好的做法,当涉及到循环尽管在JavaScript元素,或与此有关的任何阵列?
这里有一个循环我经常使用的一个很好的形式。 您创建从for语句迭代变量,你不需要检查length属性,通过节点列表进行遍历时,它可以是昂贵的特制。 但是, 你要小心 ,你不能使用它,如果任何在数组中的值的可能是“falsy”。 在实践中,我只遍历不包含空值(像的NodeList)对象的数组时使用它。 但我喜欢它的语法糖。
var list = [{a:1,b:2}, {a:3,b:5}, {a:8,b:2}, {a:4,b:1}, {a:0,b:8}];
for (var i=0, item; item = list[i]; i++) {
// Look no need to do list[i] in the body of the loop
console.log("Looping: index ", i, "item" + item);
}
请注意,这也可以向后(只要你的名单没有使用循环['-1']
属性)
var list = [{a:1,b:2}, {a:3,b:5}, {a:8,b:2}, {a:4,b:1}, {a:0,b:8}];
for (var i = list.length - 1, item; item = list[i]; i--) {
console.log("Looping: index ", i, "item", item);
}
ES6更新
for...of
给你的名字,但不是指数,因为现有ES6
for (let item of list) {
console.log("Looping: index ", "Sorry!!!", "item" + item);
}
请注意,在某些情况下,你需要以相反的顺序循环(但你也可以使用我- )。
例如有人想使用新的getElementsByClassName
的功能回路在给定类的元素和改变这一类。 他发现,两个要素只有一个被改变(FF3)。
这是因为该函数返回现场节点列表,这因此反映在DOM树的变化。 走在回避这个问题,相反的顺序列表。
var menus = document.getElementsByClassName("style2");
for (var i = menus.length - 1; i >= 0; i--)
{
menus[i].className = "style1";
}
在增加指数的进展,当我们问索引1,FF检查DOM和与蓝紫魅力,这是原始DOM的第二个跳过的第一个项目,因此返回初始第3项!
我喜欢做:
var menu = document.getElementsByTagName('div'); for (var i = 0; menu[i]; i++) { ... }
还有就是要在每个迭代上数组的长度没有电话。
在AT快速大喊危险,我会得到一个javascript助手库像jQuery的或原型它们封装逻辑尼斯方法-都有一个。每个方法/迭代器做到这一点-他们都在努力使其跨浏览器兼容
编辑:这个答案被张贴在2008年今天,更好的结构存在。 这种特殊的情况下,可以用一个来解决.forEach
。
我想用第一种形式是可能的路要走,因为它可能是迄今为止已知的宇宙中最常见的循环结构,因为我不相信反向环路节省你在现实中的任何时间(还是做增量/递减和在每次迭代的比较)。
这是识别和读取别人的代码,绝对是一件好事。
我有一个非常类似的问题早与document.getElementsByClassName()。 我不知道什么是节点列表当时。
var elements = document.getElementsByTagName('div');
for (var i=0; i<elements.length; i++) {
doSomething(elements[i]);
}
我的问题是,我期望元素将是一个数组,但事实并非如此。 该节点列表Document.getElementsByTagName()返回的是迭代的,但你不能把它array.prototype方法。
但是,您可以填充像这样的节点列表元素的数组:
var myElements = [];
for (var i=0; i<myNodeList.length; i++) {
var element = myNodeList[i];
myElements.push(element);
};
之后,你可以随时打电话.innerHTML或.style或东西在你的数组中的元素。
我也建议使用简单的方法(KISS - !)
- 但一些优化可寻,即不是为了考试的阵列一次以上的长度:
var elements = document.getElementsByTagName('div');
for (var i=0, im=elements.length; im>i; i++) {
doSomething(elements[i]);
}
另见我的安德鲁套期测试评论...
我只是试图运行测试来比较简单的迭代中,我介绍了优化和反向做/同时,其中一个阵列中的元素中的每一个循环进行测试。
唉,也难怪,我测试了三款浏览器有非常不同的结果,但优化的简单的迭代在所有速度最快 - !)
测试:
500,000元素的数组建立真正的测试外,对于每次迭代的特定阵列元素的值被揭示。
测试运行10次。
IE6:
结果:
很简单:984,922,937,984,891,907,906,891,906,906
平均:923.40毫秒。
优化:766,766,844,797,750,750,765,765,766,766
平均:773.50毫秒。
反向做/时:3375,1328,1516,1344,1375,1406,1688,1344,1297,1265
平均:1593.80毫秒。 (注意一个特别尴尬的结果)
歌剧9.52:
结果:
很简单:344,343,344,359,343,359,344,359,359,359
平均:351.30毫秒。
优化:281,297,297,297,297,281,281,297,281,281
平均:289.00毫秒
反向做/时:391,407,391,391,500,407,407,406,406,406
平均:411.20毫秒。
火狐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毫秒。
由胡安·门德斯提供循环的形式是非常有益和实用的,我改变一点点,所以现在它的工作原理-假,空,零和空字符串了。
var items = [
true,
false,
null,
0,
""
];
for(var i = 0, item; (item = items[i]) !== undefined; i++)
{
console.log("Index: " + i + "; Value: " + item);
}
我知道你不想听到的,但我认为最好的做法是最易读在这种情况下。 只要循环没有从这里计算到月球,性能增益不会uhge不够。
我更喜欢for循环,因为它是更具可读性。 从长度循环至0将比循环从0到长度更有效率。 并使用逆转while循环比福尔循环更有效,因为你说的。 我没有与比较结果的链接的网页了,但我记得的差异在不同的浏览器不同。 对于某些浏览器的逆转,而循环是快一倍。 不过这都没有区别,如果你循环“小”阵列。 在你的榜样机壳元件的长度将是“小”
我认为你有两种选择。 对于DOM元素,如jQuery和喜欢的框架给你迭代的好方法。 第二种方法是在for循环。
我喜欢用TreeWalker如果集合元素是根节点的孩子。
我知道这个问题是旧的 - 但这里的另一个极为简单的解决方案...
var elements = Array.from(document.querySelectorAll("div"));
然后它可以用于像任何,标准阵列。