Why is forEach not working for children?

后端 未结 5 1624
梦毁少年i
梦毁少年i 2020-12-14 00:36

I have a

with some child
in it. E.g.

&
相关标签:
5条回答
  • 2020-12-14 00:47

    Because .children contains an HTMLCollection [MDN], not an array. An HTMLCollection object is an array-like object, which exposes a .length property and has numeric properties, just like arrays, but it does not inherit from Array.prototype and thus is not an array.

    You can convert it to an array using Array.prototype.slice:

    var children = [].slice.call(document.getElementById(...).children);
    

    ECMAScript 6 introduces a new API for converting iterators and array-like objects to real arrays: Array.from [MDN]. Use that if possible since it makes the intent much clearer.

    var children = Array.from(document.getElementById(...).children);
    
    0 讨论(0)
  • 2020-12-14 00:51

    A cleaner and more modern way to convert a HTMLCollection like .children to an array to use forEach() (or map(), etc.) is to use the spread synthax ... in an array [].

    var children = [...document.getElementById('x').children];
    

    for example:

    [...document.getElementById('x').children].forEach(child => console.log(child))
    

    This is an es6 feature. It will work on all modern browser.

    [...document.getElementById('niceParent').children].forEach(child => console.log(child.textContent))
    <div id="niceParent">
      <div>a</div>
      <div>b</div>
      <div>c</div>
      <div>d</div>
    </div>

    0 讨论(0)
  • 2020-12-14 00:52

    Element.children is not an array. It is an object called an HTMLCollection. These do not have an array’s methods (though they do have the length property).

    To loop through it, you'll have to convert it into an array, which you can do using Array.prototype.slice:

    var children = Array.prototype.slice.call(document.getElementById("niceParent").children);
    
    children.forEach(…);
    
    0 讨论(0)
  • 2020-12-14 00:53

    If you need a clean approach with a lightweight npm module to resolve above issue, please check this out https://www.npmjs.com/package/foreach-array

    Ex:

    import each from 'foreach-array';
    
    const array = ['First Name', 'Last Name', 'Country'];
    
    each(array, (value, index, array) => {
        console.log(index + ': ' + value);
    });
    
    // Console log output will be:
    //      0: First Name
    //      1: Last Name
    //      2: Country
    

    For your scenario it is document.getElementById("niceParent").children instead of array in the above example

    0 讨论(0)
  • 2020-12-14 01:05

    You can also do this:

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

    And after this you can call forEach on your collection:

    document.getElementById("niceParent").children.forEach(...)
    

    The best and most secure way would be actually to only add forEach in cases when it doesn't already exist:

    if (window.NodeList && !NodeList.prototype.forEach) {
       NodeList.prototype.forEach = Array.prototype.forEach;
    }
    if (window.HTMLCollection && !HTMLCollection.prototype.forEach) {
       HTMLCollection.prototype.forEach = Array.prototype.forEach;
    }
    
    0 讨论(0)
提交回复
热议问题