代码之家  ›  专栏  ›  技术社区  ›  Guss

如何在javascript中将dom节点列表转换为数组?

  •  74
  • Guss  · 技术社区  · 14 年前

    我有一个接受HTML节点列表的javascript函数,但是它需要一个javascript数组(它在上面运行一些数组方法),我想将 Document.getElementsByTagName 返回一个DOM节点列表。

    起初我想用一些简单的方法,比如:

    Array.prototype.slice.call(list,0)
    

    这在所有浏览器中都可以很好地工作,当然,除了Internet Explorer返回错误“jscript object expected”,显然是由 Document.getElement* 方法不是足够作为函数调用目标的JScript对象。

    注意:我不介意编写特定于Internet Explorer的代码,但我不允许使用任何JavaScript库(如jQuery),因为我正在编写一个嵌入到第三方网站中的小部件,并且我无法加载将为客户端造成冲突的外部库。

    我的最后一项工作是迭代dom节点列表并自己创建一个数组,但是有更好的方法吗?

    7 回复  |  直到 6 年前
        1
  •  41
  •   hippietrail    12 年前

    NODLIST是 host objects ,使用 Array.prototype.slice 主机对象上的方法不能保证工作,ECMAScript规范说明:

    切片函数能否成功应用于主机对象取决于实现。

    我建议您制作一个简单的函数来迭代 NodeList 并添加每个 数组的现有元素:

    function toArray(obj) {
      var array = [];
      // iterate backwards ensuring that length is an UInt32
      for (var i = obj.length >>> 0; i--;) { 
        array[i] = obj[i];
      }
      return array;
    }
    
        2
  •  99
  •   ρяσѕρєя K    8 年前

    ES6 您可以按如下方式使用:

    • 推广算子

       var elements = [... nodelist]
      
    • 使用 Array.from

       var elements = Array.from(nodelist)
      

    更多参考资料 https://developer.mozilla.org/en-US/docs/Web/API/NodeList

        3
  •  16
  •   vsync    6 年前

    使用 spread (ES2015) 很容易做到: [...document.querySelectorAll('p')]

    (可选:使用 Babel 将上述ES6代码转换为ES5语法)


    在浏览器的控制台中进行尝试,看看它的神奇之处:

    for( links of [...document.links] )
      console.log(links);
    
        4
  •  9
  •   Gena Shumilkin    9 年前

    使用这个简单的技巧

    <Your array> = [].map.call(<Your dom array>, function(el) {
        return el;
    })
    
        5
  •  6
  •   Brett Zamir    11 年前

    虽然它不是一个真正合适的填充程序,但是由于没有规范要求使用DOM元素,所以我已经制作了一个允许您使用的填充程序。 slice() 以这种方式: https://gist.github.com/brettz9/6093105

    更新 :当我在dom4规范的编辑器中提出这个问题(询问他们是否可以向主机对象添加自己的限制(以便规范要求实现者在与数组方法一起使用时正确转换这些对象)时,超出了允许实现独立性的ecmascript规范),他回答说“主机对象是MOR”根据ES6/IDL,E或更低的过时率。“我看到了 http://www.w3.org/TR/WebIDL/#es-array 规范可以使用这个IDL定义“平台数组对象”,但是 http://www.w3.org/TR/domcore/ 似乎没有将新的IDL用于 HTMLCollection (尽管看起来可能是为了 Element.attributes 虽然它只显式地声明它正在使用WebIDL作为domstring和domstimestamp)。我看到了 [ArrayClass] (继承自array.prototype)用于 NodeList (和) NamedNodeMap 现在已弃用,取而代之的是将继续使用它的唯一项, 元素属性 )在任何情况下,它看起来都是标准的。ES6 Array.from 对于这样的转换,也可能比必须指定更方便。 Array.prototype.slice 在语义上比 [].slice() (和较短的形式, Array.slice() (一个“数组通用”),据我所知,并没有成为标准行为。

        6
  •  3
  •   Strelok    14 年前
    var arr = new Array();
    var x= ... get your nodes;
    
    for (i=0;i<x.length;i++)
    {
      if (x.item(i).nodeType==1)
      {
        arr.push(x.item(i));
      }
    }
    

    这应该有效,跨浏览器,并为您提供所有“元素”节点。

        7
  •  2
  •   Bharata colxi    6 年前

    今天,在2018年,我们可以使用EcmaScript 2015(第6版)或ES6,但并非所有浏览器都能理解它(例如,IE不能理解所有的浏览器)。如果需要,可以使用ES6,如下所示: var array = [... NodeList]; ( as spread operator var array = Array.from(NodeList); .

    在其他情况下(如果不能使用ES6),可以使用最短的方法来转换 NodeList Array :

    var array = [].slice.call(NodeList, 0); .

    例如:

    var nodeList = document.querySelectorAll('input');
    //we use "{}.toString.call(Object).slice(8, -1)" to find the class name of object
    console.log({}.toString.call(nodeList).slice(8, -1)); //NodeList
    
    var array = [].slice.call(nodeList, 0);
    console.log({}.toString.call(array).slice(8, -1)); //Array
    
    var result = array.filter(function(item){return item.value.length > 5});
    
    for(var i in result)
      console.log(result[i].value); //credit, confidence
    <input type="text" value="trust"><br><br>
    <input type="text" value="credit"><br><br>
    <input type="text" value="confidence">

    但是如果你想在 DOM 节点列表很简单,则不需要转换 NODLIST 数组 . 可以循环访问 NODLIST 使用:

    var nodeList = document.querySelectorAll('input');
    // Calling nodeList.item(i) isn't necessary in JavaScript
    for(var i = 0; i < nodeList.length; i++)
        console.log(nodeList[i].value); //trust, credit, confidence
    <input type=“text”value=“trust”><br><br>
    <input type=“text”value=“credit”><br><br>
    <input type=“text”value=“confidence”>

    别想用了 for...in for each...in 枚举列表中的项,因为这也将枚举 NODLIST 如果脚本假定它只需要处理元素对象,则会导致错误。也, for..in 不保证以任何特定的顺序参观酒店。 for...of 循环将正确地循环nodelist对象。

    也可以看到: