Вопрос по arrays, foreach, getelementsbytagname, javascript – JavaScript: цикл по всем элементам, возвращаемым из getElementsByTagName

38

Я пытаюсь перебрать все элементы отgetElementsByTagName("input") используя forEach. Есть идеи, почему это не работает в FF, Chrome или IE?


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

Теперь в ES6 NodeList естьforEach, но HTMLCollection все еще не делаетт. К несчастью,getElementsByTagName возвращает HTMLCollection. Рассмотреть возможность использованияquerySelectorAll Eric
Обоснование почему нет:forEachstackoverflow.com/questions/13433799/... Ciro Santilli 新疆改造中心996ICU六四事件

Ваш Ответ

9   ответов
8

input это не массив, этоHTMLCollection Использоватьfor петля была бы лучше.

И с тех порHTMLCollectionэто массивные объекты, которые вы можетеcall Array#forEach на это так

Array.prototype.forEach.call(input, ShowResults);
2

что и у массивов. Вы можете проверить это, набрав это в консоли javascript вашего браузера.

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

И консоль вернетсяtrue еслиelements (в этом случае) имеет метод, называемыйforEach звонить.

4

s, потому что вход - это коллекция html. html collection don 'не для каждого.

вы можете легко преобразовать его в массив с помощью 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/

4

Причина, это не работает, потому чтоgetElementsByTagName» возвращает объект типа массива, а не фактический массив. Если вы не знаете, здесьКак они оба выглядят:

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

Таким образом, поскольку Array-подобные объекты наследуются отObject.prototype» вместо 'Array.prototype», это означает, что массив, как O, объекты могутt получить доступ к общим методам-прототипам Array, таким как forEach (), push (), map (), filter () и slice ().

Надеюсь, это поможет!

Это очень хорошее объяснение Dvir
1

getElementsByTagName возвращаетHTMLCollection, которые не имеютforEach метод. Но там'Простая настройка, которая позволит вам перебиратьforEach без создание промежуточного массива: используйтеquerySelectorAll вместо.querySelectorAll возвращаетNodeListи современные браузеры имеютNodeList.prototype.forEach метод:

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

Еще одно преимущество использованияquerySelectorAll является то, что он принимает через запятуюстроки запроса, которые гораздо более гибкие и точные, чем просто имена тегов. Например, строка запроса

.container1 > span, .container2 > span

будет соответствоватьspans, которые являются потомками элементов с классомcontainer1 или же :container2

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>

1

Я сделал это:

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

Теперь вы можете использовать карту на каждом.HTMLCollection

document.getElementsByTagName("input").map(
    input => console.log(input)
);
опрятное решение, спасибо Agu V
31

Yay, ES6:

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

Документ MDN для оператора распространения ()...

Теперь в ES6 вы можете использоватьforEach для NodeList, но не для HTMLCollection.getElementsByTagName возвращает HTMLCollection, тогда какquerySelectorAll возвращает NodeList. Eric
1

В ES6 вы можете использоватьspread оператор для преобразования HtmlCollection в массив. увидеть этот вопросПочему можноя использую Array.forEach для коллекции элементов Javascript?

input = [...input]
input.forEach(ShowResults)
61


    
    
    
        <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>
    

или использовать для цикла.

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

и измените функцию ShowResults на:

function ShowResults(value) {
   alert(value);
}
Я пытался использовать это:msdn.microsoft.com/en-us/library/ie/ff679980%28v=vs.94%29.aspx slayernoah
ЗаArray.prototype.slice.call(input) Вы можете использовать стенографию.[].slice.call(input) PhilT
У меня есть> 1000 скрытых полей ввода в форме. Какой вариант будет наиболее эффективным в этом случае? slayernoah
Они оба идентичны. Не стесняйтесь использовать все, что вы хотите. Dvir

Похожие вопросы