HTMLCollection तत्वों के लिए लूप के लिए


405

मैं सभी तत्वों की आईडी प्राप्त करने की कोशिश कर रहा हूँ HTMLCollectionOf। मैंने निम्नलिखित कोड लिखा है:

var list = document.getElementsByClassName("events");
console.log(list[0].id);
for (key in list) {
    console.log(key.id);
}

लेकिन मुझे कंसोल में निम्नलिखित आउटपुट मिला:

event1
undefined

जो मुझे उम्मीद नहीं थी। दूसरा कंसोल आउटपुट क्यों है, undefinedलेकिन पहला कंसोल आउटपुट क्या है event1?


23
जब कथन में ... के बारे में है तो शीर्षक "foreach" क्यों कहता है? गुगली करते समय मैं दुर्घटना से यहाँ आया था।
mxt3

@ mxt3 खैर, मेरी समझ में, यह जावा में प्रत्येक लूप के लिए एक होलोग्राम था (समान काम किया)।

1
@ mxt3 मैंने भी यही सोचा था! लेकिन स्वीकृत उत्तर के माध्यम से पढ़ने के बाद, मुझे यह लाइन मिली, जिसने Array.from () का उपयोग करते हुए मेरी फ़ॉरचेक समस्या को हल कर दिया:Array.from(document.getElementsByClassName("events")).forEach(function(item) {
होल्डऑफ़हेंजर

जवाबों:


839

मूल प्रश्न के जवाब में, आप for/inगलत तरीके से उपयोग कर रहे हैं । आपके कोड में, keyइंडेक्स है। इसलिए, छद्म-सरणी से मान प्राप्त करने के लिए, आपको करना होगा list[key]और आईडी प्राप्त करना होगा, आप करेंगे list[key].id। लेकिन, आपको for/inपहली बार में ऐसा नहीं करना चाहिए ।

सारांश (दिसंबर 2018 में जोड़ा गया)

कभी भी for/inएक नोडलिस्ट या HTMLCollection पुनरावृति करने के लिए उपयोग न करें । इससे बचने के कारणों का वर्णन नीचे किया गया है।

आधुनिक ब्राउज़रों के सभी हाल के संस्करण (सफारी, फ़ायरफ़ॉक्स, क्रोम, एज) सभी for/ofडोम सूची पर पुनरावृत्ति का समर्थन करते हैं जैसे nodeListया HTMLCollection

यहाँ एक उदाहरण है:

var list = document.getElementsByClassName("events");
for (let item of list) {
    console.log(item.id);
}

पुराने ब्राउज़रों को शामिल करने के लिए (IE जैसी चीजों सहित), यह हर जगह काम करेगा:

var list= document.getElementsByClassName("events");
for (var i = 0; i < list.length; i++) {
    console.log(list[i].id); //second console output
}

आप का उपयोग क्यों नहीं करना चाहिए के लिए स्पष्टीकरण for/in

for/inकिसी वस्तु के गुणों को पुनरावृत्त करने के लिए है। इसका मतलब है कि यह किसी वस्तु के सभी चलने योग्य गुणों को वापस कर देगा। हालांकि यह किसी सरणी (रिटर्न ऐरे एलिमेंट्स या छद्म-एरे तत्व) के लिए काम करता दिखाई दे सकता है, यह ऑब्जेक्ट के अन्य गुणों को भी लौटा सकता है जो कि आप नहीं हैं, जो एरे-जैसे तत्वों से उम्मीद कर रहे हैं। और, अनुमान करें कि क्या, HTMLCollectionया nodeListवस्तु दोनों में अन्य गुण हो सकते हैं जो for/inपुनरावृत्ति के साथ वापस आ जाएंगे । मैंने अभी इसे क्रोम में आज़माया है और इसे जिस तरह से आप इसे पुनरावृत्त कर रहे हैं, उसे सूची में आइटम पुनः प्राप्त करेंगे (अनुक्रमित 0, 1, 2, आदि ...), लेकिन यह भी गुणों lengthऔर itemगुणों को पुनः प्राप्त करेगा । for/inयात्रा बस एक HTMLCollection के लिए काम नहीं करेगा।


देखें http://jsfiddle.net/jfriend00/FzZ2H/ कारण है कि आप के साथ एक HTMLCollection पुनरावृति नहीं कर सकता के लिएfor/in

फ़ायरफ़ॉक्स में, आपका for/inपुनरावृत्ति इन वस्तुओं को लौटाएगा (ऑब्जेक्ट के सभी चलने योग्य गुण):

0
1
2
item
namedItem
@@iterator
length

उम्मीद है, अब आप देख सकते हैं कि आप for (var i = 0; i < list.length; i++)इसके बजाय इसका उपयोग क्यों करना चाहते हैं ताकि आप इसे प्राप्त कर सकें 0, 1और 2आपकी यात्रा में।


नीचे इस बात का विवरण दिया गया है कि 2015-2018 की समयावधि में ब्राउज़र कैसे विकसित हुए हैं और आपको पुनरावृति के अतिरिक्त तरीके प्रदान कर रहे हैं। इनमें से किसी को भी अब आधुनिक ब्राउज़रों की आवश्यकता नहीं है क्योंकि आप ऊपर वर्णित विकल्पों का उपयोग कर सकते हैं।

2015 में ईएस 6 के लिए अपडेट

ES6 में जोड़ा गया है Array.from()जो एक सरणी जैसी संरचना को वास्तविक सरणी में बदल देगा। इस तरह से किसी को सीधे सूची की गणना करने की अनुमति मिलती है:

"use strict";

Array.from(document.getElementsByClassName("events")).forEach(function(item) {
   console.log(item.id);
});

अप्रैल 2016 तक वर्किंग डेमो (फ़ायरफ़ॉक्स, क्रोम और एज में): https://jsfiddle.net/jfriend00/8ar4xn2s/


2016 में ईएस 6 के लिए अपडेट

अब आप अपने कोड में इसे जोड़कर NodeListऔर इसके साथ निर्माण के लिए ES6 का उपयोग कर सकते हैं HTMLCollection:

NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
HTMLCollection.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];

फिर, आप कर सकते हैं:

var list = document.getElementsByClassName("events");
for (var item of list) {
    console.log(item.id);
}

यह क्रोम, फ़ायरफ़ॉक्स और एज के वर्तमान संस्करण में काम करता है। यह काम करता है क्योंकि यह NodeList और HTMLCollection प्रोटोटाइप दोनों के लिए एरेयर इटरेटर को संलग्न करता है ताकि जब / पुनरावृत्तियों के लिए उन्हें पुनरावृति करने के लिए एरे इटरेटर का उपयोग करें।

कार्य डेमो: http://jsfiddle.net/jfriend00/joy06u4e/


दिसंबर 2016 में ES6 के लिए दूसरा अपडेट

दिसंबर 2016 तक, Symbol.iteratorसमर्थन को Chrome v54 और फ़ायरफ़ॉक्स v50 में बनाया गया है , इसलिए नीचे दिया गया कोड अपने आप काम करता है। यह अभी एज के लिए बिल्ट-इन नहीं है।

var list = document.getElementsByClassName("events");
for (let item of list) {
    console.log(item.id);
}

वर्किंग डेमो (क्रोम और फ़ायरफ़ॉक्स में): http://jsfiddle.net/jfriend00/3ddpz8sp/

दिसंबर 2017 में ES6 के लिए तीसरा अपडेट

दिसम्बर 2017 के रूप में, एक के लिए एज 41.16299.15.0 में यह क्षमता काम करता है nodeListके रूप में document.querySelectorAll()नहीं, बल्कि एक HTMLCollectionके रूप में document.getElementsByClassName()तो आप मैन्युअल रूप से इटरेटर एक के लिए एज में इसका इस्तेमाल करने के आवंटित करने के लिए HTMLCollection। यह एक कुल रहस्य है कि वे एक संग्रह प्रकार को क्यों ठीक करेंगे, लेकिन दूसरे को नहीं। लेकिन, आप कम से कम document.querySelectorAll()ES6 के परिणाम का उपयोग कर सकते हैंfor/of एज के वर्तमान संस्करणों में सिंटैक्स हैं।

मैंने उपरोक्त jsFiddle को भी अपडेट किया है इसलिए यह दोनों का परीक्षण करता है HTMLCollectionऔरnodeList अलग-अलग आउटपुट को jsFiddle में ही कैप्चर करता है।

मार्च 2018 में ES6 के लिए चौथा अपडेट

मेसकिएब के अनुसार, Symbol.iteratorसफारी में समर्थन का निर्माण किया गया है, इसलिए आप या for (let item of list)तो उपयोग कर सकते हैंdocument.getElementsByClassName()document.querySelectorAll()

अप्रैल 2018 में ES6 के लिए पांचवां अपडेट

जाहिर है, एक HTMLCollectionसाथ iterating के लिए समर्थन करते हैंfor/of 2018 में फॉल 18 में आ जाएगा।

नवंबर 2018 में ईएस 6 के लिए छठा अपडेट

मैं इस बात की पुष्टि कर सकता हूं कि Microsoft Edge v18 (जो कि 2018 के विंडोज अपडेट में शामिल है) के साथ, अब आप एक HTMLCollection और NodeList दोनों को एज में / a के साथ जोड़ सकते हैं।

इसलिए, अब सभी आधुनिक ब्राउज़रों में for/ofHTMLCollection और NodeList दोनों वस्तुओं के पुनरावृत्ति के लिए देशी समर्थन शामिल है ।


1
बहुत विस्तृत अपडेट के लिए धन्यवाद जैसा कि जेएस ने अपडेट किया है। यह शुरुआती लोगों को अन्य लेखों / पदों के संदर्भ में इस सलाह को समझने में मदद करता है जो केवल एक विशिष्ट जेएस रिलीज पर लागू होते हैं।
Brownmagik352

उत्कृष्ट उत्तर, अद्भुत अद्यतन समर्थन .. धन्यवाद।
cossacksman

79

आप s या s पर for/ उपयोग नहीं कर सकते । हालांकि, अगर आप कुछ का उपयोग कर सकते विधियों, जब तक आप उन्हें और में पारित या के रूप मेंinNodeListHTMLCollectionArray.prototype.call()NodeListHTMLCollectionthis

तो jfriend00 के forलूप के विकल्प के रूप में निम्नलिखित पर विचार करें :

var list= document.getElementsByClassName("events");
[].forEach.call(list, function(el) {
    console.log(el.id);
});

एमडीएन पर एक अच्छा लेख है जो इस तकनीक को शामिल करता है। ब्राउज़र संगतता के बारे में उनकी चेतावनी पर ध्यान दें:

[...] एक मेजबान वस्तु (जैसे NodeList) thisको एक देशी विधि (जैसे forEach) में पास करना सभी ब्राउज़रों में काम करने की गारंटी नहीं है और कुछ में विफल होने के लिए जाना जाता है।

इसलिए जब यह दृष्टिकोण सुविधाजनक है, तो एक forलूप सबसे ब्राउज़र-संगत समाधान हो सकता है।

अद्यतन (अगस्त 30, 2014): आखिरकार आप ES6 for/of का उपयोग करने में सक्षम होंगे !

var list = document.getElementsByClassName("events");
for (const el of list)
  console.log(el.id);

यह क्रोम और फ़ायरफ़ॉक्स के हाल के संस्करणों में पहले से ही समर्थित है।


1
बहुत अच्छा! मैंने इस तकनीक का उपयोग चयनित विकल्पों के मूल्यों को प्राप्त करने के लिए किया है <select multiple>। उदाहरण:[].map.call(multiSelect.selectedOptions, function(option) { return option.value; })
XåpplI'-I0llwlg'I -

1
मैं इस के लिए एक ES2015 समाधान की तलाश में था, इसलिए उस for ... ofकाम की पुष्टि करने के लिए धन्यवाद ।
रिचर्ड टर्नर

60

ES6 में, आप कुछ ऐसा कर सकते हैं [...collection], या Array.from(collection),

let someCollection = document.querySelectorAll(someSelector)
[...someCollection].forEach(someFn) 
//or
Array.from(collection).forEach(someFn)

उदाहरण के लिए: -

    navDoms = document.getElementsByClassName('nav-container');
    Array.from(navDoms).forEach(function(navDom){
     //implement function operations
    });

@ डैनियल ने अनुमान लगाया कि मैंने क्या किया है, उथले क्लोन की तरह एक संरचना है
मिडो

मैं देख रहा हूँ, धन्यवाद - अब मुझे वह दस्तावेज मिल गया है जिसकी मुझे तलाश थी: developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
DanielM

मैं हमेशा इसका इस्तेमाल करता हूं, ऐरे.फ्रॉम की तुलना में आंखों के लिए बहुत आसान है, मुझे आश्चर्य है कि अगर इसमें काफी प्रदर्शन या मेमोरी कमियां हैं। उदाहरण के लिए, अगर मुझे टेबल रो की कोशिकाओं को पुनरावृत्त करने की आवश्यकता है, तो मैं [...row.cells].forEachइसके बजाय एक का उपयोग करता हूंrow.querySelectorAll('td')
Mojimi

16

आप इस दो पंक्तियों को जोड़ सकते हैं:

HTMLCollection.prototype.forEach = Array.prototype.forEach;
NodeList.prototype.forEach = Array.prototype.forEach;

HTMLCollection getElementsByClassName और getElementsByTagName द्वारा वापस आ गया है

NodeList द्वारा वापसी की जाती है querySelectorAll

इस तरह आप एक आगे कर सकते हैं:

var selections = document.getElementsByClassName('myClass');

/* alternative :
var selections = document.querySelectorAll('.myClass');
*/

selections.forEach(function(element, i){
//do your stuffs
});

यह उत्तर इतना प्रभावी लगता है। क्या चीज हाथ आई है?
Peheje

2
पकड़ यह है कि यह समाधान IE11 पर काम नहीं करता है! अच्छा समाधान हालांकि।
राहुल गाबा


7

मैं IE 11 में forEach का उपयोग करने में एक समस्या थी और यह भी Firefox 49

मुझे इस तरह एक वर्कअराउंड मिला है

Array.prototype.slice.call(document.getElementsByClassName("events")).forEach(function (key) {
        console.log(key.id);
    }

IE11 के लिए महान समाधान! एक आम तकनीक हुआ करती थी ...
mb21

6

Array.fromका उपयोग करने के लिए वैकल्पिक हैArray.prototype.forEach.call

प्रत्येक के लिए: Array.prototype.forEach.call(htmlCollection, i => { console.log(i) });

नक्शा: Array.prototype.map.call(htmlCollection, i => { console.log(i) });

ect ...


6

forयदि आप IE9 या इसके बाद के संस्करण पर हैं तो बचने के लिए es6 सुविधाओं का उपयोग करने का कोई कारण नहीं है।

ES5 में, दो अच्छे विकल्प हैं। सबसे पहले, आप "ऋण" Arrayका उल्लेख ईशान उल्लेख केforEach रूप में कर सकते हैं

लेकिन इससे भी बेहतर ...

का उपयोग करें Object.keys(), जो स्वचालित रूप से "गुण" के लिए है और फ़िल्टर करता है forEach

यही है, Object.keysअनिवार्य रूप से एक के for... inसाथ करने के बराबर है HasOwnProperty, लेकिन बहुत चिकनी है।

var eventNodes = document.getElementsByClassName("events");
Object.keys(eventNodes).forEach(function (key) {
    console.log(eventNodes[key].id);
});

5

मार्च 2016 तक, क्रोम 49.0 में, इसके लिए for...ofकाम करता है HTMLCollection:

this.headers = this.getElementsByTagName("header");

for (var header of this.headers) {
    console.log(header); 
}

यहाँ देखें प्रलेखन

लेकिन यह केवल तभी काम करता है यदि आप निम्नलिखित वर्कअराउंड का उपयोग करने से पहले करते हैं for...of:

HTMLCollection.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];

उसी के for...ofसाथ उपयोग करने के लिए आवश्यक है NodeList:

NamedNodeMap.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];

मुझे विश्वास है कि / आशा है कि for...ofजल्द ही उपरोक्त वर्कअराउंड के बिना काम करेंगे। खुला मुद्दा यहाँ है:

https://bugs.chromium.org/p/chromium/issues/detail?id=401699

अपडेट: नीचे देखें एक्सकॉन्जर की टिप्पणी: यह अप्रैल 2016 के रूप में तय किया गया है। आपको HTMLCollection.prototype [Symbol.iterator] = Array.prototype [Symbol.iterator] को जोड़ने की आवश्यकता नहीं है; के साथ ... के लिए एक HTMLCollection पर पुनरावृति


4
यह अप्रैल 2016 के रूप में तय किया गया है। आपको इसके साथ HTMLCollection.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];पुनरावृति जोड़ने की आवश्यकता नहीं है । HTMLCollectionfor...of
8


2

आसान वर्कअराउंड जो मैं हमेशा उपयोग करता हूं

let list = document.getElementsByClassName("events");
let listArr = Array.from(list)

इसके बाद आप चयन पर किसी भी वांछित ऐरे तरीकों को चला सकते हैं

listArr.map(item => console.log(item.id))
listArr.forEach(item => console.log(item.id))
listArr.reverse()

1

यदि आप ES के पुराने संस्करणों का उपयोग करते हैं, (उदाहरण के लिए ES5), तो आप उपयोग कर सकते हैं as any:

for (let element of elementsToIterate as any) {
      console.log(element);
}

0

आप इसे बदलना चाहते हैं

var list= document.getElementsByClassName("events");
console.log(list[0].id); //first console output
for (key in list){
    console.log(list[key].id); //second console output
}

5
FYI करें, मेरा जवाब देखें कि यह ठीक से काम क्यों नहीं करेगा। for (key in list)के कई गुण वापस आ जाएगी HTMLCollectionकि संग्रह में आइटम होने के लिए नहीं होती हैं।
jfriend00
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.