एक सरणी पर forEach का उपयोग करके getElementsByClassName परिणामों में "TypeError: अपरिभाषित एक फ़ंक्शन नहीं है"


91

में मेरी JSFiddle , मैं बस तत्वों की एक सरणी से पुनरावृति करने की कोशिश कर रहा हूँ। सरणी गैर-रिक्त है, जैसा कि लॉग स्टेटमेंट सिद्ध होता है। फिर भी forEachमुझे कॉल करने के लिए (इतना उपयोगी नहीं) "अनक्रेडेड TypeError: undefinedएक फ़ंक्शन नहीं है" त्रुटि।

मैं कुछ बेवकूफ कर रहा होगा; मैं क्या गलत कर रहा हूं?

मेरा कोड:

var arr = document.getElementsByClassName('myClass');
console.log(arr);
console.log(arr[0]);
arr.forEach(function(v, i, a) {
  console.log(v);
});
.myClass {
  background-color: #FF0000;
}
<div class="myClass">Hello</div>


8
arrएक सरणी नहीं है, लेकिन ए HTMLCollection। यह एक सरणी के रूप में एक ही तरीके नहीं है। developer.mozilla.org/en-US/docs/Web/API/… । यहां इसके बारे में एक SO पोस्ट यहां तक ​​कि है: stackoverflow.com/questions/13433799/…
इयान

कुछ [1,2,3].forEach(function(v,i,a) { console.log(v); });ठीक है। मेरे उदाहरण में इस और सरणी के बीच क्या अंतर है?
जेर

आपके पास अपने उदाहरण में कोई सरणी नहीं है । आपको क्या लगता है कि यह एक सरणी है?
इयान

3
@ जेर: arr instanceof Arrayपरिणामस्वरूप falseयह Arrayऑब्जेक्ट के किसी भी प्रोटोटाइप तरीके का लाभ नहीं उठा सकता है जैसे कि Array.prototype.forEach ()arrएक HTMLCollection और ऑब्जेक्ट की तरह एक सरणी है (लेकिन इसे या तात्कालिकता से विरासत में नहीं मिलता है Array)। इसलिए आपका स्टैण्डर्ड forलूप काम करेगा क्योंकि यह ऑब्जेक्ट के इंडेक्स के माध्यम से पुनरावृत्त करता है और इसका प्रोटोटाइप नहीं है Array
नोप

1
@ जेर- आपको निर्मित और मेजबान वस्तुओं के बीच के अंतरों को देखना चाहिए। पूर्व ECMA-262 के अनुरूप, बाद में केवल उतना ही जितना मेजबान की इच्छा है। DOM में कई ऑब्जेक्ट्स हैं जो इंडेक्स (डॉक्युमेंट्स ।images, document.forms, form.elements, select.options, इत्यादि) तक सदस्यों को एक्सेस करने की अनुमति देते हैं। NodeList इंटरफ़ेस
रोबग

जवाबों:


162

ऐसा इसलिए है क्योंकि HTMLCollectiondocument.getElementsByClassName देता है , सरणी नहीं।

सौभाग्य से यह एक "एरे-लाइक" ऑब्जेक्ट है (जो बताता है कि यह लॉग क्यों है जैसे कि यह एक ऑब्जेक्ट था और आप एक मानक forलूप के साथ पुनरावृति क्यों कर सकते हैं ), इसलिए आप ऐसा कर सकते हैं:

[].forEach.call(document.getElementsByClassName('myClass'), function(v,i,a) {

ES6 के साथ (आधुनिक ब्राउज़रों पर या बैबल के साथ), आप उपयोग भी कर सकते हैं Array.fromजो सरणी जैसी वस्तुओं से सरणियाँ बनाता है:

Array.from(document.getElementsByClassName('myClass')).forEach(v=>{

या सरणी में ऑब्जेक्ट की तरह सरणी को फैलाएं:

[...document.getElementsByClassName('myClass'))].forEach(v=>{

2
@ जेर argumentsएक है। jQuery के ऑब्जेक्ट एक और हैं। आप खुद एक बना सकते हैं:var a = {"0": "str1", "1": "str2", length: 2}
इयान

1
यहाँ हम फिर से पुराने ब्राउज़रों के साथ चलते हैं ... एक देशी विधि में एक मेजबान वस्तु को पास करना IE 8 और उससे कम में विफल हो जाएगा। शायद किसी को परवाह नहीं है, लेकिन कुछ हो सकता है। ;-) ओह, यह getElementsByClassName का समर्थन नहीं करता है , लेकिन querySelectorAll('.myClass')काम करना चाहिए। मैं अभी भी पुनरावृत्तियों के लिए नोडलिस्ट एपीआई में जोड़े जाने की प्रतीक्षा कर रहा हूं। :-(
RobG

2
@ जेर: एक साइड-नोट के रूप में यदि आप किसी भी कारण Array.prototype.forEachसे लूप से बाहर निकलने का इरादा रखते हैं तो आप ऐसा नहीं करेंगे। अगर आपको बाद में मानक forलूप का उपयोग करने की आवश्यकता है या यदि आप ऐरे ऑब्जेक्ट का उपयोग करना चाहते हैं Array.prototype.everyया Array.prototype.some(ध्यान दें कि IE8 या उससे कम में हर / कुछ समर्थित नहीं हैं)
Nope

1
@ यदि आपको ऑब्जेक्ट के लिए "सरणी-जैसा" होना चाहिए, तो आपको ब्याह की आवश्यकता होगी। यहां लॉग की तुलना करें: jsbin.com/sigut/1/edit
Denys Séguret

1
@ इयान टीबीएच "सरणी-जैसी" की परिभाषा बहुत ही अस्पष्ट है और उपयोग पर निर्भर करती है। कभी कभी मैं शामिल नहीं है spliceकि परिभाषा लेकिन जब मैं और अधिक "सरणी की तरह" होना चाहते हैं उपयोग करने के लिए सक्षम होने के लिए map, filter, और इतने पर है, तो मैं इसे शामिल हैं। सरल पुनरावृत्ति का उपयोग forEachकरने की आवश्यकता नहीं है splice
डेनिस सेगुरेट

11

कोशिश करें कि यह काम करे:

<html>
  <head>
    <style type="text/css">
    </style>
  </head>
  <body>
   <div class="myClass">Hello</div>
   <div class="myClass">Hello</div>

<script type="text/javascript">
    var arr = document.getElementsByClassName('myClass');
    console.log(arr);
    console.log(arr[0]);
    arr = [].slice.call(arr); //I have converted the HTML Collection an array
    arr.forEach(function(v,i,a) {
        console.log(v);
    });
</script>


<style type="text/css">
    .myClass {
    background-color: #FF0000;
}
</style>

  </body>
</html>

0

उस स्थिति में जब आप किसी विशिष्ट वर्ग के प्रत्येक तत्व की आईडी तक पहुँचना चाहते हैं, जो आप निम्न कार्य कर सकते हैं:

    Array.from(document.getElementsByClassName('myClass')).forEach(function(element) {
        console.log(element.id);
    });
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.