Javascript - объединение нескольких списков узлов вместе - PullRequest
17 голосов
/ 12 марта 2010

Первоначально я просил элегантный способ имитировать функциональность Array.concat() на результатах функции getElementsByTagName в IE или более старых браузерах, потому что казалось, что concat не поддерживается. Только, конечно, это так - причина, по которой возвращенный объект не поддерживал его, заключается в том, что он не Array. Oops!

getElementsByTagName фактически возвращает NodeList. Таким образом, реальный вопрос заключается в следующем: что является хорошим способом получить единый список всех элементов формы в документе (input, select, textarea, button) для их циклического прохождения? Массив не требуется ... один NodeList тоже будет идеальным.

Обратите внимание, что я использую IE6, поскольку он предназначен для корпоративной интрасети (хотя скоро IE8).

Ответ, который я придумал, был:

  • Стало проще и, вероятно, лучше работать, просто поместить код в отдельную функцию и вызвать его три раза с различными списками узлов, а не беспокоиться о хорошем способе объединить их в один. 1019 *

  • В конечном итоге я перешел на использование MooTools (после нескольких часов чтения сравнений всех различных фреймворков). Итак, теперь получить массив элементов, которые я хочу, очень просто. Я рекомендую использовать подобный javascript-фреймворк, а не пытаться понять, как лучше поступить. Конечно, я полностью за то, что изучаю сырой язык (именно поэтому я так долго воздерживался от использования фреймворка), но это не всегда самый быстрый способ начать работу, что в бизнесе часто имеет такое же значение как улучшение способности кодера с языком.

Обновление: почти через 2 года я бы просто использовал jQuery и покончил с этим!

Ответы [ 6 ]

30 голосов
/ 12 марта 2010

Чтобы объединить нодлисты, преобразуйте их в массивы, используя Array.prototype.slice.call, а затем объедините их как обычно.

var a = Array.prototype.slice.call(document.getElementsByTagName("p")),
    b = Array.prototype.slice.call(document.getElementsByTagName("div"))

var c = a.concat(b);

Редактировать: (Отвечая на ваш комментарий)

Если у вас есть только несколько типов элементов, это нормально, но производительность снижается с увеличением количества вызовов DOM. Может быть лучше и быстрее сделать document.getElementsByTagName('*'), пройтись по списку и выбрать элементы с требуемым nodeName.

Еще одна вещь, которую нужно иметь в виду, это то, что Array.prototype.slice метод, использованный выше, может не работать во ВСЕХ браузерах. Посмотрите на стартовую строку комментария # 723 в sizzle.js (механизм выбора позади jQuery)

Конечно, лучше всего использовать библиотеку, такую ​​как jQuery, которая обрабатывает всю головную боль. Вы можете просто сделать:

$("input, select, textarea, <other tags>")
3 голосов
/ 12 апреля 2017

С оператором ES6 вы можете сделать

let arr = [...nodeList1, ...nodeList2];
3 голосов
/ 23 июня 2013
function mergeNodeLists(a, b) {
  var slice = Array.prototype.slice;
  return slice.call(a).concat(slice.call(b));
}

console.log( mergeNodeLists( inputs, selects ) ); // => [input, select]

1 голос
/ 12 января 2018

Как отмечено в документации MDN , вы также можете использовать Array.from для преобразования NodeList в массив в браузерах, которые его поддерживают.

1 голос
/ 12 марта 2010
var a1=document.getElementsByTagName('div'),
a2=document.getElementsByTagName('button');
a1=[].slice.call(a1, 0,a1.length).concat([].slice.call(a2, 0,a2.length))
0 голосов
/ 27 марта 2016

Я думал, что было бы больше ответов, чем это, так или иначе, я дал этому шанс и придумал следующую функцию, хотя мне пришлось слегка ударить головой.

function group_elements(element, tags) {
   var elements = element.getElementsByTagName('*');
   var results  = [];
   for ( var i = 0; i < elements.length; ++i ) {
      if ( tags.indexOf(elements[i].nodeName.toLowerCase()) > -1 ) {
         results.push(elements[i]);
      }
   }
   return results;
}


var form  = document.getElementById('form');
var tags = ['input', 'select'];
console.log(group_elements(form, tags));
...