जेएस: Array.forEach का उपयोग करके getElementsByClassName के परिणाम पर पुनरावृति


240

मैं कुछ DOM तत्वों पर पुनरावृति करना चाहता हूँ, मैं यह कर रहा हूँ:

document.getElementsByClassName( "myclass" ).forEach( function(element, index, array) {
  //do stuff
});

लेकिन मुझे एक त्रुटि मिली:

document.getElementsByClassName ("myclass")। forEach कोई फ़ंक्शन नहीं है

मैं फ़ायरफ़ॉक्स 3 का उपयोग कर रहा हूं इसलिए मुझे पता है कि दोनों मौजूद हैं getElementsByClassNameऔर Array.forEachमौजूद हैं। यह ठीक काम करता है:

[2, 5, 9].forEach( function(element, index, array) {
  //do stuff
});

getElementsByClassNameएक ऐरे का परिणाम है ? यदि नहीं, तो यह क्या है?

जवाबों:


384

DOM4 में निर्दिष्ट के रूप में , यह एक है HTMLCollection(आधुनिक ब्राउज़रों में, कम से कम। पुराने ब्राउज़र वापस आ गए NodeList)।

सभी आधुनिक ब्राउज़रों में (बहुत कुछ भी अन्य IE <= 8), आप ऐरे की forEachविधि को कॉल कर सकते हैं , इसे तत्वों की सूची ( मान के अनुसार) HTMLCollectionया इसे पास कर सकते हैं :NodeListthis

var els = document.getElementsByClassName("myclass");

Array.prototype.forEach.call(els, function(el) {
    // Do stuff here
    console.log(el.tagName);
});

// Or
[].forEach.call(els, function (el) {...});

यदि आप ईएस 6 (यानी आप इंटरनेट एक्सप्लोरर को सुरक्षित रूप से अनदेखा कर सकते हैं या आप ईएस 5 ट्रांसपिलर का उपयोग कर रहे हैं) का उपयोग करने की खुशी की स्थिति में हैं, तो आप उपयोग कर सकते हैं Array.from:

Array.from(els).forEach((el) => {
    // Do stuff here
    console.log(el.tagName);
});

29
पहले इसे किसी ऐरे में बदलने की जरूरत नहीं है। बस उपयोग करें [].forEach.call(elsArray, function () {...})
- एसई बुराई है

1
यह एक नॉडलिस्ट नहीं है। यह एक सरणी जैसी वस्तु है। मुझे नहीं लगता कि इसका कोई उदाहरण है। querySelectorAllविधि एक NodeList देता है, हालांकि।
मक्सीम वी।

2
@MaksimVi। आप बिलकुल सही कह रहे हैं: DOM4 निर्दिष्ट करता है कि (जो कि बहुत समान है, लेकिन नॉडलिस्ट नहीं है) document.getElementsByClassName()वापस लौटना चाहिए HTMLCollection। गलती को इंगित करने के लिए धन्यवाद।
टिम डाउन

@MaksimVi: मुझे आश्चर्य है कि क्या कुछ बिंदु पर बदल गया। मैं आमतौर पर इन चीजों की जांच करता हूं।
टिम डाउन

1
@ टिमडाउन, HTMLCollectionटिप के लिए धन्यवाद । अब मैं अंत HTMLCollection.prototype.forEach = Array.prototype.forEach;में अपने कोड में उपयोग कर सकता हूं।
मक्सीम वी।

70

आप Array.fromसंग्रह को सरणी में बदलने के लिए उपयोग कर सकते हैं , जो कि Array.prototype.forEach.callनिम्न तरीके से क्लीनर है :

Array.from(document.getElementsByClassName("myclass")).forEach(
    function(element, index, array) {
        // do stuff
    }
);

पुराने ब्राउज़रों में जो समर्थन नहीं करते हैं Array.from, आपको बैबेल जैसे कुछ का उपयोग करने की आवश्यकता है।


ES6 इस वाक्यविन्यास को भी जोड़ता है:

[...document.getElementsByClassName("myclass")].forEach(
    (element, index, array) => {
        // do stuff
    }
);

...सभी सरणी जैसी वस्तुओं पर काम के साथ विनाशकारी आराम करें, न केवल खुद को गिरफ्तार करता है, फिर मूल्यों से एक सरणी का निर्माण करने के लिए अच्छे पुराने सरणी सिंटैक्स का उपयोग किया जाता है।


जबकि वैकल्पिक फ़ंक्शन querySelectorAll(जो थोड़े getElementsByClassNameअप्रचलित बनाता है ) एक संग्रह देता है जिसमें forEachमूल रूप से, अन्य तरीके जैसे mapया filterगायब हैं, इसलिए यह सिंटैक्स अभी भी उपयोगी है:

[...document.querySelectorAll(".myclass")].map(
    (element, index, array) => {
        // do stuff
    }
);

[...document.querySelectorAll(".myclass")].map(element => element.innerHTML);

6
नोट: जैसा कि सुझाए गए (बैबल) के बिना ट्रांसपिलिंग, यह आईई <एज, ओपेरा, सफारी <9, एंड्रॉइड ब्राउज़र, एंड्रॉइड के लिए क्रोम, ... आदि में संगत नहीं है। स्रोत: मोज़िला देव डॉक्स
सीन

30

या आप उपयोग कर सकते हैं querySelectorAllजो रिटर्न NodeList :

document.querySelectorAll('.myclass').forEach(...)

आधुनिक ब्राउज़रों द्वारा समर्थित (एज सहित, लेकिन IE नहीं):
क्या मैं querySelectorAll NodeList.prototyp.forEach () का उपयोग कर सकता हूं

MDN: Document.querySelectorAll ()


4
GetElementByClassName से अधिक के प्रदर्शन के दंड को ध्यान में रखें
Szabolcs Páll

3
DOM को संशोधित करने जैसे अन्य गहन कार्यों की तुलना में प्रदर्शन का दंड नगण्य है । अगर मैं 1 मिलीसेकंड में इनमें से 60,000 को निष्पादित करता हूं , तो मुझे पूरा यकीन है कि यह किसी भी उचित उपयोग के लिए एक मुद्दा नहीं होगा :)
icl7126

1
आपने गलत बेंचमार्क लिंक किया है। यहाँ सही एक नापा जा रहा है ।.net/Benchmark/Show/4076 /0/ बस इसे मेरे लो-एंड फोन पर चलाया, 160k / s बनाम 380k / s मिला। चूँकि आपने DOM मैनिपुलेशन का उल्लेख किया है, यहाँ यह भी बताया गया है कि बहुत से उपाय ..net / Benchmarks / Show / 5705 /0/ समझे 50k / s बनाम 130k / s। जैसा कि आप देखते हैं कि डोम को हेरफेर करने के लिए यह और भी धीमा है, संभवतः नोडलिस्ट के स्थिर होने के कारण (जैसा कि दूसरों द्वारा उल्लेख किया गया है)। अभी भी ज्यादातर उपयोग के मामलों में लापरवाह है, लेकिन फिर भी लगभग 3 गुना धीमा।
Szabolcs Páll

14

संपादित करें: यद्यपि HTML के नए संस्करणों में रिटर्न प्रकार बदल गया है (टिम डाउन का अद्यतन उत्तर देखें), नीचे दिया गया कोड अभी भी काम करता है।

जैसा कि दूसरों ने कहा है, यह एक नोडलिस्ट है। यहाँ एक पूर्ण, काम करने का उदाहरण आप कोशिश कर सकते हैं:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <script>
            function findTheOddOnes()
            {
                var theOddOnes = document.getElementsByClassName("odd");
                for(var i=0; i<theOddOnes.length; i++)
                {
                    alert(theOddOnes[i].innerHTML);
                }
            }
        </script>
    </head>
    <body>
        <h1>getElementsByClassName Test</h1>
        <p class="odd">This is an odd para.</p>
        <p>This is an even para.</p>
        <p class="odd">This one is also odd.</p>
        <p>This one is not odd.</p>
        <form>
            <input type="button" value="Find the odd ones..." onclick="findTheOddOnes()">
        </form>
    </body>
</html>

यह Win 7 पर IE 9, FF 5, Safari 5 और Chrome 12 में काम करता है।


9

का परिणाम getElementsByClassName()एक ऐरे नहीं है, बल्कि एक सरणी जैसी वस्तु है । विशेष रूप से यह एक कहा जाता है HTMLCollection, के साथ भ्रमित होने की नहीं NodeList( जो इसका अपना forEach()तरीका है )।

ES2015 के साथ एक सरल तरीका साथ प्रयोग के लिए एक सरणी जैसी वस्तु कन्वर्ट करने के लिए Array.prototype.forEach()है कि अभी तक का उल्लेख नहीं किया गया है प्रसार ऑपरेटर या उपयोग करने के लिए है फैल वाक्य रचना :

const elementsArray = document.getElementsByClassName('myclass');

[...elementsArray].forEach((element, index, array) => {
    // do something
});

2
मुझे लगता है कि आधुनिक ब्राउज़रों में ऐसा करने का वास्तव में सही तरीका है। यह सटीक उपयोग मामला फैला हुआ है जिसे हल करने के लिए सिंटैक्स बनाया गया था।
मैट कोरोस्टॉफ़


3

जैसा कि पहले ही कहा गया है, getElementsByClassNameएक HTMLCollection देता है , जिसे इस रूप में परिभाषित किया गया है

[Exposed=Window]
interface HTMLCollection {
  readonly attribute unsigned long length;
  getter Element? item(unsigned long index);
  getter Element? namedItem(DOMString name);
};

पहले, कुछ ब्राउज़रों ने इसके बजाय एक NodeList लौटाया ।

[Exposed=Window]
interface NodeList {
  getter Node? item(unsigned long index);
  readonly attribute unsigned long length;
  iterable<Node>;
};

यह अंतर महत्वपूर्ण है, क्योंकि DOM4 अब NodeList को चलने योग्य के रूप में परिभाषित करता है।

वेब आईडीएल के मसौदे के अनुसार ,

एक इंटरफ़ेस को लागू करने वाली वस्तुएँ जो मानों के अनुक्रम को प्राप्त करने के लिए पुनरावृत्त होने के लिए चलने योग्य समर्थन के रूप में घोषित की जाती हैं।

नोट : ECMAScript लैंग्वेज बाइंडिंग में, एक इंटरफेस जो कि चलने योग्य है, उसके इंटरफेस प्रोटोटाइप ऑब्जेक्ट पर "एंट्रीज़", "फॉरएच", "कीज़", "वैल्यूज़" और @@ इटरेटर गुण होंगे ।

इसका मतलब है कि, यदि आप उपयोग करना चाहते हैं, तो आप forEachएक DOM विधि का उपयोग कर सकते हैं जो एक NodeList देता है , जैसे querySelectorAll

document.querySelectorAll(".myclass").forEach(function(element, index, array) {
  // do stuff
});

ध्यान दें कि यह अभी तक व्यापक रूप से समर्थित नहीं है। Node.childNodes की फॉरच विधि भी देखें ?


1
क्रोम 49 रिटर्नforEach in not a function
विटाली ज़डनेविच

@VitalyZdanevich क्रोमियम 50
ओरोल

क्रोम 50 पर मुझे मिल रहा हैdocument.querySelectorAll(...).forEach is not a function
विटाली ज़ेडेनविच

@VitalyZdanevich यह क्रोमियम 50 पर काम करता है, और अभी भी क्रोमियम 53 पर काम करता है। शायद इसे क्रोम 50 पर शिप करने के लिए पर्याप्त स्थिर नहीं माना गया।
ओरिऑल


1

यह सुरक्षित तरीका है:

var elements = document.getElementsByClassName("myclass");
for (var i = 0; i < elements.length; i++) myFunction(elements[i]);

0

getElementsByClassNameआधुनिक ब्राउज़रों में HTMLCollection देता है।

जो है सरणी की तरह तर्क के समान वस्तु जो iteratable कर रहा है for...ofपाश नीचे क्या देख MDN डॉक इसके बारे में कह रहा है:

के लिए ... स्टेटमेंट में एक से अधिक चलने-फिरने योग्य वस्तुओं पर चलने वाला एक लूप बनता है , जिसमें शामिल हैं: अंतर्निहित स्ट्रिंग, एरे, एरे जैसी वस्तुएं (जैसे, तर्क या नॉडलिस्ट), टाइपएड्रे, मैप, सेट, और उपयोगकर्ता द्वारा परिभाषित इटरेबल्स। यह वस्तु के प्रत्येक विशिष्ट गुण के मूल्य के लिए निष्पादित किए जाने वाले बयानों के साथ एक कस्टम पुनरावृत्ति हुक को आमंत्रित करता है।

उदाहरण

for (let element of getElementsByClassName("classname")){
   element.style.display="none";
}

ऐसा नहीं है, टाइपस्क्रिप्ट के अनुसार:error TS2488: Type 'HTMLCollectionOf<Element>' must have a '[Symbol.iterator]()' method that returns an iterator.
कछुए

@TurtlesAreCute, यहाँ ओपी जावास्क्रिप्ट नहीं टाइपस्क्रिप्ट का उपयोग कर रहा है और मैंने वैनिला जेएस की सिफारिश के अनुसार उत्तर दिया है, इसलिए टाइपस्क्रिप्ट में यह समस्या के लिए अलग समाधान हो सकता है।
हरितसिंह गोहिल

@TurtlesAreCute, वैसे यह टाइपस्क्रिप्ट में भी काम कर रहा है, लेकिन आपको सही प्रकार के चर का उल्लेख करना होगा जो विशेष सीएसएस वर्ग के तत्व को रखता है, इसलिए इसे तदनुसार डाल सकते हैं, विस्तार से इस उत्तर को देखें ।
हरितसिंह गोहिल

0

यहाँ मैंने jsperf पर एक परीक्षण बनाया है: https://jsperf.com/vanillajs-loop-through-elements-of-class

Chrome और Firefox में सबसे परफ्यूम वर्जन document.getElementsByClassName के साथ संयोजन में लूप के लिए अच्छा पुराना है:

var elements = document.getElementsByClassName('testClass'), elLength = elements.length;
for (var i = 0; i < elLength; i++) {
    elements.item(i).textContent = 'Tested';
};

सफारी में यह संस्करण विजेता है:

var elements = document.querySelectorAll('.testClass');
elements.forEach((element) => {
    element.textContent = 'Tested';
});

यदि आप सभी ब्राउज़रों के लिए सबसे शानदार संस्करण चाहते हैं, तो यह इस प्रकार हो सकता है:

var elements = document.getElementsByClassName('testClass');
Array.from(elements).map(
    (element) => {
        return element.textContent = 'Tested';
    }
);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.