web-dev-qa-db-ja.com

JavaScript:getElementsByTagNameから返されたすべての要素をループします

ForEachを使用してgetElementsByTagName("input")から返されたすべての要素をループしようとしています。 FF、ChromeまたはIEでこれが機能しない理由はありますか?

<html>
    <head>
    </head>
    <body>
        <input type="text" value="" />
        <input type="text" value="" />
        <script>
            function ShowResults(value, index, ar) {
                alert(index);
            }
            var input = document.getElementsByTagName("input");
            alert(input.length);
            input.forEach(ShowResults);
    </script>
    </body>
</html>
44
slayernoah

これでノードリストを配列に変換する必要があります:

<html>
    <head>
    </head>
    <body>
        <input type="text" value="" />
        <input type="text" value="" />
        <script>
            function ShowResults(value, index, ar) {
                alert(index);
            }
            var input = document.getElementsByTagName("input");
            var inputList = Array.prototype.slice.call(input);
            alert(inputList.length);
            inputList.forEach(ShowResults);
    </script>
    </body>
</html>

またはforループを使用します。

for(i = 0;i < input.length; i++)
{
    ShowResults(input[i].value);
}

showResults関数を次のように変更します。

function ShowResults(value) {
   alert(value);
}
68
Dvir

イェーイ、ES6:

const children = [...parent.getElementsByTagName('tag')];
children.forEach((child) => { /* Do something; */ });

スプレッド演算子のMDN Doc(...

37
jtheletter

inputは配列ではないため、 HTMLCollectionforループを使用することをお勧めします。

HTMLCollectionsは配列のようなオブジェクトなので、 callArray#forEachこのように

Array.prototype.forEach.call(input, ShowResults);
8
grape_mao

入力がhtmlコレクションであるためです。 htmlコレクションにはforEachがありません。

array.prototype.sliceによって簡単に配列に変換できます

例:

function ShowResults(value, index, ar) {
            alert(index);
        }
        var input = document.getElementsByTagName("input");
        alert(input.length);
input = Array.prototype.slice.call(input)
        input.forEach(ShowResults);

http://jsfiddle.net/fPuKt/1/

5
Daniel Dykszak

その理由は、「getElementsByTagName」が実際の配列ではなくオブジェクトのような配列を返すためです。あなたが気付いていない場合、ここにそれらの両方がどのように見えるかです:-

var realArray = ['a', 'b', 'c'];
var arrayLike = {
  0: 'a',
  1: 'b',
  2: 'c',
  length: 3
};

したがって、配列のようなオブジェクトは「Array.prototype」ではなく「Object.prototype」から継承するため、これは配列のようなオブジェクトが共通の配列プロトタイプにアクセスできないことを意味しますforEach()、Push()、map()、filter()、およびslice()などのメソッド。

お役に立てば幸いです!

4
Naman Sancheti

getElementsByTagNameは、HTMLCollectionメソッドを持たないforEachを返します。ただし、中間配列を作成するforEachwithoutで反復できる単純な調整があります:use querySelectorAll代わりに。 querySelectorAllNodeListを返し、最新のブラウザにはNodeList.prototype.forEachメソッドがあります:

document.querySelectorAll('input')
  .forEach((input) => {
    console.log(input.value);
  });
<input type="text" value="foo">
<input type="text" value="bar">

querySelectorAllを使用するもう1つの利点は、カンマ区切りクエリ文字列を受け入れることです。これは、タグ名よりもはるかに柔軟で正確です。たとえば、クエリ文字列

.container1 > span, .container2 > span

container1またはcontainer2のクラスを持つ要素の子であるspansのみに一致します。

document.querySelectorAll('.container1 > span, .container2 > span')
  .forEach((span) => {
    span.classList.add('highlight');
  });
.highlight {
  background-color: yellow;
}
<div class="container1">
  <span>foo</span>
  <span>bar</span>
</div>
<div class="container2">
  <span>baz</span>
</div>
<div class="container3">
  <span>buzz</span>
</div>

メソッドが組み込まれていない古代のブラウザでNodeList.prototype.forEachを使用する場合は、単に polyfill を追加します。次のスニペットはIE11で動作します。

// Polyfill:
if (window.NodeList && !NodeList.prototype.forEach) {
  NodeList.prototype.forEach = function(callback, thisArg) {
    thisArg = thisArg || window;
    for (var i = 0; i < this.length; i++) {
      callback.call(thisArg, this[i], i, this);
    }
  };
}

// Main code:
document.querySelectorAll('.container1 > span, .container2 > span')
  .forEach(function(span) {
    span.classList.add('highlight');
  });
.highlight {
  background-color: yellow;
}
<div class="container1">
  <span>foo</span>
  <span>bar</span>
</div>
<div class="container2">
  <span>baz</span>
</div>
<div class="container3">
  <span>buzz</span>
</div>
3

HTMLCollectionsには配列と同じメソッドはありません。ブラウザのjavascriptコンソールでこれを傾けることで、このことを確認できます。

var elements = document.getElementsByClassName('some-class');
'forEach' in elements;

そして、true(この場合)が呼び出すelementsというメソッドを持っている場合、コンソールはforEachを返します。

2
Andrés Torres

ES6では、spread演算子を使用して、HtmlCollectionを配列に変換できます。この質問を参照してください Javascript要素のコレクションでArray.forEachを使用できないのはなぜですか?

input = [...input]
input.forEach(ShowResults)
1
inostia

これは私がしました:

HTMLCollection.prototype.map = Array.prototype.map;

すべてのHTMLCollectionでマップを使用できるようになりました。

document.getElementsByTagName("input").map(
    input => console.log(input)
);
1