Почему nodelist не имеет forEach?
я работал над коротким сценарием, чтобы изменить <abbr> внутренний текст элементов, но обнаружил, что nodelist нет forEach метод. Я знаю, что nodelist не наследует от Array, но разве это не похоже на forEach было бы полезно иметь метод? Есть ли конкретная проблема реализации, о которой я не знаю, что предотвращает добавление forEach до nodelist?
примечание: Я знаю, что Dojo и jQuery оба forEach в какой-то форме для их элементов. Я не могу использовать из-за ограничений.
10 ответов:
NodeList теперь имеет forEach () во всех основных браузерах
посмотреть nodeList forEach () на MDN.
оригинальный ответ
ни один из этих ответов разъяснить почему NodeList не наследует от массива, что позволяет ему иметь
forEachи все остальное.ответ найден на этом es-обсуждение темы. Короче говоря, он ломает паутину:
проблема была код, который неверно предположил, что instanceof означает, что экземпляр был массивом в сочетании с массивом.прототип.функция concat.
в библиотеке закрытия Google была ошибка, которая вызвала сбой почти всех приложений Google из-за этого. Библиотека была обновлена, как только это было найдено, но там все еще может быть код, который делает то же самое неверное предположение в сочетании с concat.
то есть, какой-то код что-то сделал как
,if (x instanceof Array) { otherArray.concat(x); } else { doSomethingElseWith(x); }concatбудет обрабатывать" реальные " массивы (не instanceof Array) по-разному от других объектов:[1, 2, 3].concat([4, 5, 6]) // [1, 2, 3, 4, 5, 6] [1, 2, 3].concat(4) // [1, 2, 3, 4]так что это означает, что приведенный выше код сломался, когда
xбыл NodeList, потому что прежде чем он пошел внизdoSomethingElseWith(x)путь, а потом он пошел вниз поotherArray.concat(x)путь, который сделал что-то странное сxне было реального массива.в течение некоторого времени было предложение для
Elementsкласс, который был настоящим подкласс Массив, и будет использоваться как "новый NodeList". Однако, это было удалено из стандарта DOM, по крайней мере, на данный момент, поскольку это было невозможно реализовать еще по целому ряду технических и технических причин.
вы можете рассмотреть возможность создания нового массива узлов.
var nodeList = document.getElementsByTagName('div'), nodes = Array.prototype.slice.call(nodeList,0); // nodes is an array now. nodes.forEach(function(node){ // do your stuff here. });Примечание: это просто список/массив ссылок на узлы, которые мы создаем здесь, без дубликатов узлов.
nodes[0] === nodeList[0] // will be true
никогда не говори никогда, это 2016 и
NodeListобъект реализовал aforEachметод в последнем chrome (v52.0.2743.116).слишком рано использовать его в производстве, так как другой браузер еще не поддерживает это (протестирован FF 49), но я бы предположил, что это будет стандартизировано в ближайшее время.
короче говоря, это конфликт дизайна для реализации этого метода.
от MDN:
почему я не могу использовать forEach или map в списке узлов?
NodeList используются очень похоже на массивы, и было бы заманчиво используйте массив.прототипные методы на них. Однако это невозможно.
JavaScript имеет механизм наследования на основе прототипов. Матрица экземпляры наследуют методы массива (например, forEach или map), поскольку их прототип цепи выглядит следующим образом:
myArray --> Array.prototype --> Object.prototype --> null(the цепочка прототипов объекта может быть получена путем вызова несколько раз Объект.getPrototypeOf)forEach, map и подобные-это собственные свойства массива.прототип объект.
в отличие от массивов, цепочка прототипов NodeList выглядит следующим образом:
myNodeList --> NodeList.prototype --> Object.prototype --> nullсписок узлов.прототип содержит элемент метода, но ни один из Матрица.прототип методы, поэтому они не могут быть использованы на NodeLists.
Источник:https://developer.mozilla.org/en-US/docs/DOM/NodeList (прокрутите вниз до почему я не могу использовать forEach или map в списке узлов?)
Если вы хотите использовать forEach на NodeList, просто скопируйте эту функцию из массива:
NodeList.prototype.forEach = Array.prototype.forEach;вот и все, теперь вы можете использовать его таким же образом, как и для массива:
document.querySelectorAll('td').forEach(function(o){ o.innerHTML = 'text'; });
в ES2015, теперь вы можете использовать
forEachметод для списка узлов.document.querySelectorAll('abbr').forEach( el => console.log(el));Посмотреть MDN Link
однако если вы хотите использовать коллекции HTML или другой массив-как объекты, в es2015, вы можете использовать
Array.from()метод. Этот метод принимает массивоподобный или итерационный объект (включая nodeList, коллекции HTML, строки и т. д.) и возвращает новый экземпляр массива. Вы можете использовать его следующим образом:const elements = document.getElementsByTagName('abbr'); Array.from(elements).forEach( el => console.log(el));как
Array.from()метод shimmable, вы можете использовать его в ES5 код такойvar elements = document.getElementsByTagName('abbr'); Array.from(elements).forEach( function(el) { console.log(el); });для получения дополнительной информации см. MDN
мое решение:
//foreach for nodeList NodeList.prototype.forEach = Array.prototype.forEach; //foreach for HTML collection(getElementsByClassName etc.) HTMLCollection.prototype.forEach = Array.prototype.forEach;
NodeList является частью DOM API. Посмотрите на привязки ECMAScript, которые также применяются к JavaScript. http://www.w3.org/TR/DOM-Level-2-Core/ecma-script-binding.html. nodeList и свойство длины только для чтения и функция item(index) для возврата узла.
ответ, вы должны повторить. Альтернативы нет. Foreach не будет работать. Я работаю с привязками JAVA DOM API и имею ту же проблему.
Проверьте MDN для Списке_узлов.по каждому элементу спецификация.
NodeList.forEach(function(item, index, nodeList) { // code block here });
в IE, используйте ответ Акуна:
[].forEach.call(NodeList, function(item, index, array) { // code block here });
Comments