【问题标题】:JavaScript NodeListJavaScript 节点列表
【发布时间】:2015-02-24 20:05:51
【问题描述】:

有没有办法加入由 2 次 document.getElementsByTagName 调用返回的 2 个 NodeList?

说,我有以下代码

var inputs = documentElement.getElementsByTagName('input');
var selects = document.getElementsByTagName('select');

我想遍历结果。是否可以一循环?

提前谢谢你!

【问题讨论】:

  • 同时或依次循环它们?

标签: javascript dom concat nodelist


【解决方案1】:

似乎您可以使用相同的 Array.prototype.slice.call 使 args 类数组对象成为一个数组。 (See here)

var inputs = document.getElementsByTagName('input');
var selects = document.getElementsByTagName('select');

inputs = Array.prototype.slice.call(inputs);
selects = Array.prototype.slice.call(selects);

var res = inputs.concat(selects);

alert(res.length);

【讨论】:

  • 我刚想说 :) +1 Prototype 和其他库使用 slice 将节点列表转换为数组。
  • 要记住的一点是,这在 Internet Explorer 或 BlackBerry 浏览器中不起作用。 jQuery 1.4 有一个有趣的测试,用于回退到循环来组合节点列表。我在这里摘录了:pastebin.com/TkTwMG17
【解决方案2】:

你不能加入它们,但你仍然可以像这样在一个循环中依次循环它们:

for ( var i = 0; i < inputs.length + selects.length; i++ ) {
    var element = ( i < inputs.length ) ? inputs[i] : selects[i-inputs.length];
}

或者,使用 jQuery,您可以一次性选择它们:

$('input, select')

【讨论】:

    【解决方案3】:
    document.querySelectorAll("input, select"); 
    

    【讨论】:

    • 需要 FF 3.1+、Safari 3.1+ 或 IE8+
    【解决方案4】:

    据我所知,NodeList 类型是不可变的(例如参见this article),这意味着您必须生成自己的对象。

    一个简单的方法就是创建一个数组并将所有元素复制到该数组中。

    var inputs = documentElement.getElementsByTagName('input');
    var selects = document.getElementsByTagName('select');
    var all = new Array(inputs.length + selects.length);
    
    var index = 0;
    for (i = 0; i < inputs.length; i++)
        all[index++] = inputs[i];
    for (i = 0; i < selects.length; i++)
        all[index++] = selects[i];
    

    all 变量然后包含两组节点的并集。

    【讨论】:

    • 无论如何它都需要 2 个循环。对于我的特定任务,我只需要循环一次结果,因此创建一个对象是不值得的。我无法加入结果,这就是我想知道的,谢谢!
    • 是的,无论如何,在我看来,使用两个循环是最清晰的解决方案。 (我考虑过单循环选项,但它并没有真正的帮助。)很高兴你有一个解决方案。
    • 好吧。那么 Array.prototype.slice.call(thatNodeListOfYours, 0); ?
    【解决方案5】:
    function mergeNodeLists(a, b) {
      var slice = Array.prototype.slice;
      return slice.call(a).concat(slice.call(b));
    }
    

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

    【讨论】:

      【解决方案6】:

      我把这个放在一起了。为每个循环执行 if.length 可能会产生一些开销,但我认为除非元素数量变得极端,否则它的开销很小。

      inputs = div.getElementsByTagName('input');
      selects = div.getElementsByTagName('select');
      for (i=0; i<inputs.length+selects.length; i++) {
          element = (i<inputs.length ? inputs[i] : selects[i-inputs.length]);
      
          // do whatever with element
      }
      

      【讨论】:

        【解决方案7】:

        我的小书签短代码:

        var e, t = d.getElementsByTagName('textarea'), u = d.getElementsByTagName('input'), i = t.length;
            while(e = (i > 0) ? t[--i] : u[-i--]){ if(e.offsetHeight > 0)... }
        

        【讨论】:

          【解决方案8】:

          首先,我认为可以使用 Array.prototype 连接数组,如下所示:

          Array.prototype.concat.call(selects, inputs);
          

          但它不起作用,所以我从节点集合中创建了一个数组并将其连接起来。看起来像这样:

          (function () {
          
              var inputs = document.getElementsByTagName('input'),
                  selects = document.getElementsByTagName('select'),
                  result,
                  i,
                  node;
          
              function convert (collection) {
                  var a = [];
                  for (var i = 0, length = collection.length; i < length; i++) {
                      a.push(collection[i]);
                  }
                  return a;
              }
          
              // concatenation && convertation
              result = Array.prototype.concat(convert(inputs), convert(selects));
              // traversing
              i = result.length;
              while(node = result[--i]) {
                  alert(node.getAttribute('name'));
              }
          
          })();
          

          【讨论】:

          • 我相信第一个技巧适用于除 IE 之外的任何(主要)浏览器。
          • 第一个技巧不适用于基于 WebKit 的浏览器(safari、chrome)
          【解决方案9】:

          现在我肯定会使用以下内容:

          Chrome、Firefox 3.5+、IE8+

          var elements = document.querySelectorAll('a');
          
          for (var i = 0, element; (element = elements[i]); i++) {
              console.log(element);
          }
          

          IE11+、Firefox 24+、Chrome 30+(已启用实验)

          let elements = document.querySelectorAll('a');
          
          for (let i = 0, element; (element = elements[i]); i++) {
              console.log(element);
          }
          

          “element = elements[i]”优于“elements.length”,因为:

          “节点列表通常被实现为带有过滤器的节点迭代器。这意味着获取像长度这样的属性是 O(n),并且通过重新检查长度来迭代列表将是 O(n^2)。 "

          与数组访问不同,据我所知是 O(1)。

          更多细节:

          【讨论】:

            【解决方案10】:

            Array.prototype.slice.call() 在 IE 7 中失败,使用这个:

            Object.prototype.getMyElements = function(tags){
                tags = tags.split(',');
                var i, j, col=[], ci=0;
                for(i=0; i<tags.length; i++) {
                    var objs = this.getElementsByTagName(tags[i]);
                    for(j=0; j<objs.length; j++) col[ci++] = objs[j];
                }
                return col;
            }
            var objs = document.getMyElements('INPUT,TEXTAREA');
            var objs = document.getElementById('myform').getMyElements('INPUT,TEXTAREA');
            

            【讨论】:

              【解决方案11】:

              试试我的方法:

               var allES = [];
               var inputs = document.getElementsByTagName("input");
                      for (i = 0; i < inputs.length; i++) {
                            allES.push(inputs[i]);
                          }
                  // gather SELECT elements
                       var selects = document.getElementsByTagName("select");
                          for ( i=0; i < selects.length; i++){
                              allES.push(selects[i]);
                              }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-11-01
                • 2011-10-16
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多