[英]What's the best way to loop through a set of elements in JavaScript?
在過去和大多數我目前的項目中,我傾向於使用這樣的for循環:
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屬性,這在迭代NodeList時特別昂貴。 但是, 您必須小心 , 如果數組中的任何值可能是“虛假” , 則無法使用它 。 在實踐中,我只在迭代不包含空值的對象數組(如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 (let item of list) {
console.log("Looping: index ", "Sorry!!!", "item" + item);
}
請注意,在某些情況下,您需要以相反的順序循環(但是您也可以使用i--)。
例如,有人想使用新的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的第2個,因此它返回第3個初始項目!
我喜歡這樣做:
var menu = document.getElementsByTagName('div');
for (var i = 0; menu[i]; i++) {
...
}
每次迭代都沒有調用數組的長度。
我認為使用第一種形式可能是要走的路,因為它可能是迄今為止已知宇宙中最常見的循環結構,並且因為我不相信反向循環可以在實際中節省你的任何時間(仍在增加/遞減和每次迭代的比較)。
其他人可識別和可讀的代碼絕對是件好事。
我之前遇到過與document.getElementsByClassName()類似的問題。 我當時不知道節點列表是什么。
var elements = document.getElementsByTagName('div');
for (var i=0; i<elements.length; i++) {
doSomething(elements[i]);
}
我的問題是我希望元素是一個數組,但事實並非如此。 nodelist Document.getElementsByTagName()返回是可迭代的,但你不能在其上調用array.prototype方法。
但是,您可以使用nodelist元素填充數組,如下所示:
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]);
}
另請參閱我對Andrew Hedges測試的評論......
我只是嘗試運行一個測試來比較一個簡單的迭代,我引入的優化和反向do / while,其中數組中的元素在每個循環中進行測試。
唉,毫不奇怪,我測試的三個瀏覽器有非常不同的結果,盡管優化的簡單迭代是最快的! - )
在實際測試之外構建具有500,000個元素的數組,對於每次迭代,顯示特定數組元素的值。
試運行10次。
結果:
簡單: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毫秒。 (注意一個特別尷尬的結果)
結果:
簡單: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毫秒。
結果:
簡單: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毫秒。
Juan Mendez提供的循環形式是非常有用和實用的,我稍微改了一下,所以現在它也可以使用 - false,null,zero和empty字符串。
var items = [
true,
false,
null,
0,
""
];
for(var i = 0, item; (item = items[i]) !== undefined; i++)
{
console.log("Index: " + i + "; Value: " + item);
}
我知道你不想聽到這個,但是:我認為在這種情況下最好的做法是最可讀的。 只要循環不計數從這里到月球,性能增益就不夠了。
我更喜歡for循環,因為它更具可讀性。 從長度到0的循環比從0到長度的循環更有效。 如你所說,使用反向while循環比foor循環更有效。 我沒有比較結果頁面的鏈接,但我記得不同瀏覽器的差異各不相同。 對於某些瀏覽器,反向while循環速度是其兩倍。 但是,如果你循環“小”數組,它沒有任何區別。 在您的示例中,元素的長度將是“小”
我認為你有兩種選擇。 對於諸如jQuery和類似框架之類的dom元素,為您提供了一種很好的迭代方法。 第二種方法是for循環。
我知道這個問題很老 - 但這是另一個非常簡單的解決方案......
var elements = Array.from(document.querySelectorAll("div"));
然后它可以像任何標准數組一樣使用。
如果元素集是根節點的子節點,我喜歡使用TreeWalker 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.